ox

The Ox programming language, compiler and tools (WIP)
Log | Files | Refs | README | LICENSE

types.h (7282B)



#pragma once

#include <libgccjit.h>
#include <stdlib.h>
#include <stdbool.h>

typedef enum {
	TOKEN_IDENT = 1006,
	TOKEN_LPAREN,
	TOKEN_RPAREN,
	TOKEN_LBRACE,
	TOKEN_RBRACE,
	TOKEN_LBRACKET,
	TOKEN_RBRACKET,
	TOKEN_EQUAL,
	TOKEN_SEMICOLON,
	TOKEN_PERCENT,
	TOKEN_COMMA,
	TOKEN_STRUCT,
	TOKEN_EXTEND,
	TOKEN_FX,
	TOKEN_FN,
	TOKEN_INT_LITERAL,
	TOKEN_FLOAT_LITERAL,
	TOKEN_STRING_LITERAL,
	TOKEN_BOOL_TRUE_LITERAL,
	TOKEN_BOOL_FALSE_LITERAL,
	TOKEN_COMP_TIME,
	TOKEN_VARIADIC,
	TOKEN_SLASH,
	TOKEN_STAR,
	TOKEN_PLUS,
	TOKEN_PLUSPLUS,
	TOKEN_MINUS,
	TOKEN_MINUSMINUS,
	TOKEN_EQUALITY,
	TOKEN_INEQUALITY,
	TOKEN_BANG,
	TOKEN_LT,
	TOKEN_GT,
	TOKEN_LT_EQ,
	TOKEN_GT_EQ,
	TOKEN_IF,
	TOKEN_ELSE,
	TOKEN_WHILE,
	TOKEN_FOR,
	TOKEN_BREAK,
	TOKEN_CONTINUE,
	TOKEN_RETURN,
	TOKEN_UNKNOWN, // NOTE: also update print_token
	TOKEN_EOF
} TokenType; // NOTE also update token_type_str!

const char* token_type_str(TokenType t);

typedef struct {
	size_t start;
	size_t end;
	size_t line;
	size_t col;
	TokenType type;
} Token;

typedef struct {
	Token* tokens;
	size_t token_count;
	size_t token_cap;
	size_t pos;
	size_t line;
	size_t col;
	const char* src;
	size_t src_len;
	const char* filename;
} Lexer;

typedef enum {
	NODE_PROGRAM = 11,
	NODE_FUNCTION_DECL,
	NODE_PARAM,
	NODE_VAR_DECL,
	NODE_VAR_ASSIGN,
	NODE_BLOCK,
	NODE_CALL_EXPR,
	NODE_RETURN,
	NODE_BREAK,
	NODE_CONTINUE,
	NODE_INT_LITERAL,
	NODE_FLOAT_LITERAL,
	NODE_STRING_LITERAL,
	NODE_BOOL_LITERAL,
	NODE_IDENT,
	NODE_TYPE,
	NODE_BINARY_EXPR,
	NODE_UNARY_EXPR,
	NODE_EXPR_STATEMENT,
	NODE_SUBSCRIPT_EXPR,
	NODE_IF,
	NODE_WHILE,
	NODE_FOR,
	NODE_EMPTY_STATEMENT,
	NODE_UNKNOWN,
} NodeType; // note: if changed, edit node_type_str!

const char* node_type_str(NodeType);
void print_node_type_str(NodeType);

/*
typedef enum {
    OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD,
    OP_POS, OP_NEG, OP_INC, OP_DEC,
    OP_BITAND, OP_BITOR, OP_BITXOR, OP_BITNOT,
    OP_SHL, OP_SHR,
    OP_LOGAND, OP_LOGOR, OP_LOGNOT,
    OP_LT, OP_LE, OP_GT, OP_GE, OP_EQ, OP_NE,
    OP_ASSIGN, OP_ADD_ASSIGN, OP_SUB_ASSIGN,
    OP_MUL_ASSIGN, OP_DIV_ASSIGN, OP_MOD_ASSIGN,
    OP_SHL_ASSIGN, OP_SHR_ASSIGN,
    OP_AND_ASSIGN, OP_XOR_ASSIGN, OP_OR_ASSIGN,
    OP_CONDITIONAL, OP_COMMA,
    OP_ADDR, OP_DEREF, OP_MEMBER, OP_PTR_MEMBER,
    OP_SUBSCRIPT, OP_CALL,
    OP_SIZEOF, OP_ALIGNOF
} OpType;
*/

typedef enum {
	OP_PLUS = 300,
	OP_MINUS,
	OP_MUL,
	OP_DIV,
	OP_MOD,
	OP_BIT_AND, // & ampersand
	OP_BIT_OR,  // |
	OP_ASSIGN,
	OP_EQUALITY,   // ==
	OP_INEQUALITY, // !=
	OP_LT_EQ,
	OP_GT_EQ,
	OP_LT,
	OP_GT,
} OpType;

typedef enum {
	OPER_MINUS = 0,
	OPER_BANG,
	OPER_PREINC,
	OPER_PREDEC,
	OPER_POSTINC,
	OPER_POSTDEC,
} UnaryOp;

typedef struct {
	size_t start;
	size_t end;
} Span;

typedef struct Node {
	NodeType type;
	struct Node* next;
	struct Scope* scope;
	const char* filename;
	size_t line, col;

	/* NOTE we will eventually add spans for condition info, etc. to print out in errors */

	union {
		/* clang-format off */
        struct { struct Node** decl; size_t len, cap; } program;
        struct { Span name; struct Node* return_type; struct Node** params; size_t p_cap, p_len; struct Node* body; bool exported; } function_decl;
        struct { Span name; struct Node* type; } param;
        struct { struct Node* cond; struct Node* then_body; struct Node* else_body; } if_statement;
        struct { struct Node* cond; struct Node* body; } while_statement;
        struct { struct Node* init; struct Node* cond; struct Node* increment; struct Node* body; } for_statement;
        struct { struct Node** stmts; size_t cap, len; } block;
        struct { Span name; struct Node* type; struct Node* init; } var_decl;
        struct { struct Node* lhs; struct Node* rhs; } var_assign;
        struct { struct Node* callee; struct Node** args; size_t cap, len; } call_expr;
        struct { struct Node* expr; } ret;
        struct { struct Node* expr; } cont;
        struct { struct Node* expr; } expr_statement;
        struct { OpType op; struct Node* lhs; struct Node* rhs; } binary_expr;
        struct { UnaryOp op; struct Node* operand; bool is_postfix; } unary_expr;
        struct { struct Node* array; struct Node* index; } subscript_expr;
        struct { double value; } number;
        struct { bool value; } boolean;
        struct { Span value; } string;
        struct { Span name; } ident;
        struct { Span name; bool is_comp_time; bool is_variadic; } ident_type;
		/* clang-format on */
	} data;
} Node;

typedef struct {
	Token* tokens;
	size_t token_count;
	size_t pos;
	const char* src;
	size_t src_len;
	const char* filename;
} Parser;

typedef struct {
	Node* node;
	const char* src;
} Ast;

typedef struct {
	Node** items;
	size_t len, cap;
} NodeVec;

typedef enum {
	// todo distinguish local/exported/param
	SYMTYPE_VOID = 108,
	SYMTYPE_INT,
	SYMTYPE_I8,
	SYMTYPE_I16,
	SYMTYPE_I32,
	SYMTYPE_I64,
	SYMTYPE_I128,
	SYMTYPE_UINT,
	SYMTYPE_U8,
	SYMTYPE_U16,
	SYMTYPE_U32,
	SYMTYPE_U64,
	SYMTYPE_U128,
	SYMTYPE_F32,
	SYMTYPE_F64,
	SYMTYPE_F128,
	SYMTYPE_FLOAT,
	SYMTYPE_STR,
	SYMTYPE_CHR,
	SYMTYPE_BOOL,
	SYMTYPE_STRUCT,
	SYMTYPE_USER,
	SYMTYPE_ARRAY,
	SYMTYPE_ENUM,
	SYMTYPE_FUNC,
	SYMTYPE_TODO,
} SymbolType; // note also update type_kind_str!

const char* type_kind_str(SymbolType);

typedef enum {
	ENUM_VALUE_INT,
	ENUM_VALUE_STRING,
} EnumValueKind;

typedef struct StructField {
	char* name;
	struct Type* type;
} StructField;

typedef struct EnumField {
	char* name;
	EnumValueKind kind;
	union { // not used?
		int int_value;
		char* string_value;
	} val;
} EnumField;

typedef struct StructMethod {
	char* name;
	struct Type* return_type;
	struct Type** param_types;
	int params_count;
	int params_cap;
	// TODO add ptr to func decl of this struct method
} StructMethod;

typedef struct Type {
	SymbolType type;

	// union {
	//     struct StructType {
	//         const char* struct_name;
	//         int fields_count;
	//         int methods_count;
	//         StructField* fields;
	//         StructMethod* methods;
	//     } struct_t;

	//     struct ArrayType {
	//         int array_size; // -1 or fixed
	//         struct Type* of_type;
	//         bool dynamic;
	//     } array_t;

	//     struct EnumType {
	//         const char* enum_name;
	//         const int fields_count;
	//         EnumField* fields;
	//         EnumValueKind value_kind;
	//     } enum_t;
	// };
} TypeInfo;

typedef struct Symbol {
	Span name;
	Node* decl;
	TypeInfo* type; // todo print all found in gen

	gcc_jit_type* ctype;
	const char* english_type;
	bool is_variadic;
	bool is_comp_time;
	union {
		gcc_jit_function* funcvalue;
		gcc_jit_lvalue* lvalue;
		gcc_jit_param* param;
		gcc_jit_rvalue* const_rvalue;
	} d;
} Symbol;

// @later NOTE: our symbols are a list, there is an argument to be made to change to a linked list;
// as a linked list will outperform an allocated list up to 12-16 elements, or so.
// @later NOTE: also consider their relation between each other and the rest of the compiler is a bit of a circulas mess;
// which is fine as long as we're boostrapping and getting it off the ground.
typedef struct Scope {
	struct Node* owner;
	struct Scope* parent;
	Symbol** symbols;
	size_t len;
	size_t cap;
	struct Scope** children;
	size_t ch_len;
	size_t ch_cap;
	int depth;
	int id;
} Scope;