Generating valid c code, more work on null values
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
clang main.cpp -I.. -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib
|
pushd %~dp0
|
||||||
|
clang main.cpp -O0 -I.. -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib
|
||||||
|
popd
|
||||||
|
|||||||
232
cgenerate.cpp
Normal file
232
cgenerate.cpp
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
|
||||||
|
#define genln(...) do{printf("\n"); gen_indent(); gen(__VA_ARGS__); }while(0)
|
||||||
|
#define gen(...) printf(__VA_ARGS__)
|
||||||
|
global S32 global_indent;
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_indent(){
|
||||||
|
for(S32 i = 0; i < global_indent; i++) gen(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo: Gen complicated decl
|
||||||
|
//array 10 ( pointer (pointer array 5 int a))
|
||||||
|
// int (*(*(a[5])))[10]
|
||||||
|
//
|
||||||
|
// 1 Get to the bottom
|
||||||
|
// 2 Add variable name
|
||||||
|
// 3 Going backwards add arrays and pointers in parens
|
||||||
|
// 4 Add type name on the left side
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_simple_decl_prefix(Ast_Resolved_Type *ast){
|
||||||
|
switch(ast->kind){
|
||||||
|
case TYPE_Int: gen("int "); break;
|
||||||
|
case TYPE_Bool: gen("bool "); break;
|
||||||
|
case TYPE_Unsigned: gen("unsigned "); break;
|
||||||
|
case TYPE_String: gen("String "); break;
|
||||||
|
case TYPE_Void: gen("void "); break;
|
||||||
|
case TYPE_Pointer:{gen_simple_decl_prefix(ast->base); gen("*");} break;
|
||||||
|
case TYPE_Array: gen_simple_decl_prefix(ast->base); break;
|
||||||
|
case TYPE_Lambda:break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_simple_decl_postfix(Ast_Resolved_Type *ast){
|
||||||
|
switch(ast->kind){
|
||||||
|
case TYPE_Int: break;
|
||||||
|
case TYPE_Bool: break;
|
||||||
|
case TYPE_Unsigned: break;
|
||||||
|
case TYPE_String: break;
|
||||||
|
case TYPE_Void: break;
|
||||||
|
case TYPE_Pointer: gen_simple_decl_postfix(ast->base); break;
|
||||||
|
case TYPE_Array: gen("[%d]", (int)ast->arr.size); gen_simple_decl_postfix(ast->arr.base); break;
|
||||||
|
case TYPE_Lambda:break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){
|
||||||
|
if(ast->kind == TYPE_Lambda) {
|
||||||
|
gen_simple_decl_prefix(ast->func.ret);
|
||||||
|
gen("(*%s)(", name.str);
|
||||||
|
For(ast->func.args){
|
||||||
|
gen_simple_decl_prefix(it[0]);
|
||||||
|
if(it != ast->func.args.end() - 1) gen(", ");
|
||||||
|
}
|
||||||
|
gen(")");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
gen_simple_decl_prefix(ast);
|
||||||
|
if(name.len) {
|
||||||
|
gen("%s", name.str);
|
||||||
|
gen_simple_decl_postfix(ast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_expr(Ast_Expr *ast){
|
||||||
|
switch(ast->kind){
|
||||||
|
Ast_Begin(AST_IDENT, Ast_Expr){
|
||||||
|
gen("%s", node->intern_val.str);
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_INT, Ast_Expr){
|
||||||
|
gen("%lld", node->int_val);
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_STR, Ast_Expr){
|
||||||
|
gen("LIT(\"%s\")", node->intern_val.str);
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_INDEX, Ast_Expr){
|
||||||
|
gen_expr(node->index.expr);
|
||||||
|
gen("[");
|
||||||
|
gen_expr(node->index.index);
|
||||||
|
gen("]");
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_UNARY, Ast_Expr){
|
||||||
|
switch(node->unary.op){
|
||||||
|
case TK_Pointer: {
|
||||||
|
gen("(*");
|
||||||
|
gen_expr(node->unary.expr);
|
||||||
|
gen(")");
|
||||||
|
} break;
|
||||||
|
case TK_Dereference: {
|
||||||
|
gen("(&");
|
||||||
|
gen_expr(node->unary.expr);
|
||||||
|
gen(")");
|
||||||
|
} break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_CAST, Ast_Expr){
|
||||||
|
gen("(");
|
||||||
|
gen("(");
|
||||||
|
gen_simple_decl(node->cast.typespec->resolved_type, {});
|
||||||
|
gen(")");
|
||||||
|
gen_expr(node->cast.expr);
|
||||||
|
gen(")");
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_COMPOUND, Ast_Expr){
|
||||||
|
gen("(");
|
||||||
|
gen_simple_decl(node->compound.type, {});
|
||||||
|
gen(")");
|
||||||
|
|
||||||
|
gen("{");
|
||||||
|
For(node->compound.exprs){
|
||||||
|
auto comp = it[0]->compound_item;
|
||||||
|
if(comp.name){
|
||||||
|
gen("[");
|
||||||
|
gen_expr(comp.name);
|
||||||
|
gen("] = ");
|
||||||
|
}
|
||||||
|
if(comp.index){
|
||||||
|
gen("[");
|
||||||
|
gen_expr(comp.index);
|
||||||
|
gen("] = ");
|
||||||
|
}
|
||||||
|
assert(comp.item);
|
||||||
|
gen_expr(comp.item);
|
||||||
|
|
||||||
|
if(!node->compound.exprs.is_last(it)) gen(", ");
|
||||||
|
}
|
||||||
|
gen("}");
|
||||||
|
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_ast(Ast *ast){
|
||||||
|
switch(ast->kind){
|
||||||
|
|
||||||
|
Ast_Begin(AST_PACKAGE, Ast_Package){
|
||||||
|
For(node->decls) gen_ast(*it);
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_VAR, Ast_Decl){
|
||||||
|
genln("");
|
||||||
|
Sym *sym = sym_get(node->name);
|
||||||
|
gen_simple_decl(sym->type, node->name);
|
||||||
|
if(node->var.expr){
|
||||||
|
gen(" = ");
|
||||||
|
gen_expr(node->var.expr);
|
||||||
|
}
|
||||||
|
gen(";");
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_CONST, Ast_Decl){
|
||||||
|
Sym *sym = sym_get(node->name);
|
||||||
|
|
||||||
|
if(sym->type->kind == TYPE_Lambda){
|
||||||
|
if(node->var.expr->kind == AST_LAMBDA){
|
||||||
|
Ast_Lambda *lambda = (Ast_Lambda *)node->var.expr;
|
||||||
|
genln("");
|
||||||
|
gen_simple_decl(lambda->ret->resolved_type, node->name);
|
||||||
|
gen("(");
|
||||||
|
For(lambda->params){
|
||||||
|
assert(it[0]->kind == AST_LAMBDA_PARAM);
|
||||||
|
gen_simple_decl(it[0]->lambda_param.typespec->resolved_type, it[0]->lambda_param.name);
|
||||||
|
if(it != (lambda->params.end() - 1)) gen(", ");
|
||||||
|
}
|
||||||
|
gen(")");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
genln("");
|
||||||
|
gen_simple_decl(sym->type, node->name);
|
||||||
|
gen(" = ");
|
||||||
|
gen_expr(node->var.expr);
|
||||||
|
gen(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(sym->type == type_int){
|
||||||
|
genln("enum { %s = %lld };", node->name.str, sym->int_val);
|
||||||
|
}
|
||||||
|
else if(sym->type == type_string){
|
||||||
|
genln("String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
parsing_error(node->pos, "Unhandled type of constant expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
test_gen(){
|
||||||
|
TEST_PARSER();
|
||||||
|
String filename = "test3.kl"_s;
|
||||||
|
String file_content = os_read_file(scratch, filename);
|
||||||
|
lex_restream(&ctx, file_content, filename);
|
||||||
|
Ast_Package *result = parse_file();
|
||||||
|
sym_insert_builtins();
|
||||||
|
eval_decl(result);
|
||||||
|
gen(R"==(
|
||||||
|
#define null_pointer 0
|
||||||
|
#define null_lambda 0
|
||||||
|
)==");
|
||||||
|
gen_ast(result);
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
66
generate.c
66
generate.c
@@ -1,66 +0,0 @@
|
|||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include "lang.h"
|
|
||||||
#include "os.h"
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
#include "common.c"
|
|
||||||
#include "memory.c"
|
|
||||||
#include "scratch.c"
|
|
||||||
#include "os_win32.c"
|
|
||||||
|
|
||||||
#include "new_lex.c"
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// String replacing util
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef struct String_Map String_Map;
|
|
||||||
struct String_Map{
|
|
||||||
String replace;
|
|
||||||
String with;
|
|
||||||
};
|
|
||||||
|
|
||||||
function void
|
|
||||||
output_template(FILE *f, String filename, String_Map *map, SizeU map_cap){
|
|
||||||
Arena *scratch = arena_begin_scratch();
|
|
||||||
String file = os_read_file(scratch, filename);
|
|
||||||
Token_Array array = lex_stream(scratch, file, filename);
|
|
||||||
for(Token *t = token_array_iter_begin(&array); t->kind != TK_End; t = token_array_iter_next(&array)){
|
|
||||||
String string = t->string;
|
|
||||||
for(SizeU i = 0; i < map_cap; i++){
|
|
||||||
if(string_compare(string, map[i].replace)){
|
|
||||||
string = map[i].with;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(f, "%.*s", (int)string.len, string.str);
|
|
||||||
if(t->kind == TK_OpenBrace) fprintf(f, "\n");
|
|
||||||
if(t->kind == TK_CloseBrace && token_array_iter_peek(&array, 0)->kind != TK_Semicolon) fprintf(f, "\n");
|
|
||||||
if(t->kind == TK_Semicolon) fprintf(f, "\n");
|
|
||||||
if(t->kind == TK_Keyword) fprintf(f, " ");
|
|
||||||
if(t[0].kind == TK_Identifier && token_array_iter_peek(&array, 0)->kind == TK_Identifier) fprintf(f, " ");
|
|
||||||
token_array_iter_peek(&array, 1);
|
|
||||||
}
|
|
||||||
arena_end_scratch();
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(){
|
|
||||||
|
|
||||||
FILE *f = fopen("generated.c", "w");
|
|
||||||
assert(f);
|
|
||||||
String_Map map[] = {
|
|
||||||
{lit("Type"), lit("Decl")},
|
|
||||||
{lit("first"), lit("list_decl.first")},
|
|
||||||
{lit("last"), lit("list_decl.last")},
|
|
||||||
{lit("remove"), lit("decl_list_remove")},
|
|
||||||
{lit("push_front"), lit("decl_dll_list_push_front")},
|
|
||||||
{lit("push"), lit("decl_dll_list_push")},
|
|
||||||
};
|
|
||||||
output_template(f, lit("dllqueue.c"), map, buff_cap(map));
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
33
ideas.cpp
33
ideas.cpp
@@ -1,33 +0,0 @@
|
|||||||
New_Data_Type::typedef int;
|
|
||||||
CONST_VAL::const 324;
|
|
||||||
|
|
||||||
Ideas::enum{
|
|
||||||
One,
|
|
||||||
Two,
|
|
||||||
Three
|
|
||||||
}
|
|
||||||
|
|
||||||
Data::struct{
|
|
||||||
first: int;
|
|
||||||
second: int;
|
|
||||||
idea: Ideas;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function_call::(first_param: Data*, second_param: int[32]){
|
|
||||||
first_param.first = 10;
|
|
||||||
first_param.second = 10;
|
|
||||||
first_param.idea = Ideas.One;
|
|
||||||
p:= first_param;
|
|
||||||
|
|
||||||
for i in 0...32 {
|
|
||||||
second_param[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 32; i++ {
|
|
||||||
second_param[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
84
lex.c
84
lex.c
@@ -27,7 +27,7 @@ function void
|
|||||||
init_default_keywords(Intern_Table *t){
|
init_default_keywords(Intern_Table *t){
|
||||||
keyword_if = intern_string(t, lit("if"));
|
keyword_if = intern_string(t, lit("if"));
|
||||||
first_keyword = keyword_if.s.str;
|
first_keyword = keyword_if.s.str;
|
||||||
|
|
||||||
keyword_cast = intern_string(t, lit("cast"));
|
keyword_cast = intern_string(t, lit("cast"));
|
||||||
keyword_for = intern_string(t, lit("for"));
|
keyword_for = intern_string(t, lit("for"));
|
||||||
keyword_else = intern_string(t, lit("else"));
|
keyword_else = intern_string(t, lit("else"));
|
||||||
@@ -44,16 +44,16 @@ init_default_keywords(Intern_Table *t){
|
|||||||
keyword_case = intern_string(t, lit("case"));
|
keyword_case = intern_string(t, lit("case"));
|
||||||
keyword_struct = intern_string(t, lit("struct"));
|
keyword_struct = intern_string(t, lit("struct"));
|
||||||
keyword_enum = intern_string(t, lit("enum"));
|
keyword_enum = intern_string(t, lit("enum"));
|
||||||
|
|
||||||
keyword_union = intern_string(t, lit("union"));
|
keyword_union = intern_string(t, lit("union"));
|
||||||
last_keyword = keyword_union.s.str;
|
last_keyword = keyword_union.s.str;
|
||||||
|
|
||||||
intern_char = intern_string(t, lit("char"));
|
intern_char = intern_string(t, lit("char"));
|
||||||
intern_void = intern_string(t, lit("void"));
|
intern_void = intern_string(t, lit("void"));
|
||||||
intern_int = intern_string(t, lit("int"));
|
intern_int = intern_string(t, lit("int"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function B32
|
function B32
|
||||||
lex_is_keyword(Intern_String str){
|
lex_is_keyword(Intern_String str){
|
||||||
B32 result = str.s.str >= first_keyword && str.s.str <= last_keyword;
|
B32 result = str.s.str >= first_keyword && str.s.str <= last_keyword;
|
||||||
return result;
|
return result;
|
||||||
@@ -61,7 +61,7 @@ lex_is_keyword(Intern_String str){
|
|||||||
|
|
||||||
typedef enum Token_Kind{
|
typedef enum Token_Kind{
|
||||||
TK_End,
|
TK_End,
|
||||||
|
|
||||||
TK_Mul,
|
TK_Mul,
|
||||||
TK_Div,
|
TK_Div,
|
||||||
TK_Mod,
|
TK_Mod,
|
||||||
@@ -69,12 +69,12 @@ typedef enum Token_Kind{
|
|||||||
TK_RightShift,
|
TK_RightShift,
|
||||||
TK_FirstMul = TK_Mul,
|
TK_FirstMul = TK_Mul,
|
||||||
TK_LastMul = TK_RightShift,
|
TK_LastMul = TK_RightShift,
|
||||||
|
|
||||||
TK_Add,
|
TK_Add,
|
||||||
TK_Sub,
|
TK_Sub,
|
||||||
TK_FirstAdd = TK_Add,
|
TK_FirstAdd = TK_Add,
|
||||||
TK_LastAdd = TK_Sub,
|
TK_LastAdd = TK_Sub,
|
||||||
|
|
||||||
TK_Equals,
|
TK_Equals,
|
||||||
TK_LesserThenOrEqual,
|
TK_LesserThenOrEqual,
|
||||||
TK_GreaterThenOrEqual,
|
TK_GreaterThenOrEqual,
|
||||||
@@ -83,15 +83,15 @@ typedef enum Token_Kind{
|
|||||||
TK_NotEquals,
|
TK_NotEquals,
|
||||||
TK_FirstCompare = TK_Equals,
|
TK_FirstCompare = TK_Equals,
|
||||||
TK_LastCompare = TK_NotEquals,
|
TK_LastCompare = TK_NotEquals,
|
||||||
|
|
||||||
TK_BitAnd,
|
TK_BitAnd,
|
||||||
TK_BitOr,
|
TK_BitOr,
|
||||||
TK_BitXor,
|
TK_Pointer,
|
||||||
TK_And,
|
TK_And,
|
||||||
TK_Or,
|
TK_Or,
|
||||||
TK_FirstLogical = TK_BitAnd,
|
TK_FirstLogical = TK_BitAnd,
|
||||||
TK_LastLogical = TK_Or,
|
TK_LastLogical = TK_Or,
|
||||||
|
|
||||||
TK_Neg,
|
TK_Neg,
|
||||||
TK_Not,
|
TK_Not,
|
||||||
TK_OpenParen,
|
TK_OpenParen,
|
||||||
@@ -106,9 +106,9 @@ typedef enum Token_Kind{
|
|||||||
TK_ThreeDots,
|
TK_ThreeDots,
|
||||||
TK_Semicolon,
|
TK_Semicolon,
|
||||||
TK_Dot,
|
TK_Dot,
|
||||||
|
|
||||||
TK_Colon,
|
TK_Colon,
|
||||||
|
|
||||||
TK_Assign,
|
TK_Assign,
|
||||||
TK_ColonAssign,
|
TK_ColonAssign,
|
||||||
TK_DivAssign,
|
TK_DivAssign,
|
||||||
@@ -123,14 +123,14 @@ typedef enum Token_Kind{
|
|||||||
TK_RightShiftAssign,
|
TK_RightShiftAssign,
|
||||||
TK_FirstAssign = TK_Assign,
|
TK_FirstAssign = TK_Assign,
|
||||||
TK_LastAssign = TK_RightShiftAssign,
|
TK_LastAssign = TK_RightShiftAssign,
|
||||||
|
|
||||||
TK_DoubleColon,
|
TK_DoubleColon,
|
||||||
TK_At,
|
TK_At,
|
||||||
TK_Decrement,
|
TK_Decrement,
|
||||||
TK_Increment,
|
TK_Increment,
|
||||||
TK_PostDecrement,
|
TK_PostDecrement,
|
||||||
TK_PostIncrement,
|
TK_PostIncrement,
|
||||||
|
|
||||||
TK_Arrow,
|
TK_Arrow,
|
||||||
TK_ExprSizeof,
|
TK_ExprSizeof,
|
||||||
TK_DocComment,
|
TK_DocComment,
|
||||||
@@ -150,14 +150,14 @@ typedef struct Token{
|
|||||||
String string;
|
String string;
|
||||||
struct{U8 *str; S64 len;};
|
struct{U8 *str; S64 len;};
|
||||||
};
|
};
|
||||||
|
|
||||||
union {
|
union {
|
||||||
U64 int_val;
|
U64 int_val;
|
||||||
F64 float_val;
|
F64 float_val;
|
||||||
String error_val;
|
String error_val;
|
||||||
Intern_String intern_val;
|
Intern_String intern_val;
|
||||||
};
|
};
|
||||||
|
|
||||||
String file;
|
String file;
|
||||||
S32 line;
|
S32 line;
|
||||||
U8 *line_begin;
|
U8 *line_begin;
|
||||||
@@ -167,7 +167,7 @@ typedef struct Token{
|
|||||||
typedef struct Lex_Stream{
|
typedef struct Lex_Stream{
|
||||||
String stream;
|
String stream;
|
||||||
S64 iter;
|
S64 iter;
|
||||||
|
|
||||||
U8 *line_begin;
|
U8 *line_begin;
|
||||||
String file;
|
String file;
|
||||||
S32 line;
|
S32 line;
|
||||||
@@ -207,7 +207,7 @@ lex_is_numeric(U8 c){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function B32
|
function B32
|
||||||
lex_is_alphanumeric(U8 c){
|
lex_is_alphanumeric(U8 c){
|
||||||
B32 result = lex_is_numeric(c) || lex_is_alphabetic(c);
|
B32 result = lex_is_numeric(c) || lex_is_alphabetic(c);
|
||||||
return result;
|
return result;
|
||||||
@@ -226,7 +226,7 @@ token_error(Token *t, String error_val){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
lex_parse_u64(Token *t){
|
lex_parse_u64(Token *t){
|
||||||
U64 result = 0;
|
U64 result = 0;
|
||||||
U64 m = 1;
|
U64 m = 1;
|
||||||
for(S64 i = t->len - 1; i >= 0; --i){
|
for(S64 i = t->len - 1; i >= 0; --i){
|
||||||
@@ -257,7 +257,7 @@ lex_advance(Lex_Stream *s){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
lex_parse_string(Lex_Stream *s, Token *t, U8 c){
|
lex_parse_string(Lex_Stream *s, Token *t, U8 c){
|
||||||
for(;;){
|
for(;;){
|
||||||
if(lexc(s) == '\\') lex_advance(s);
|
if(lexc(s) == '\\') lex_advance(s);
|
||||||
@@ -301,14 +301,14 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
while(lexc(s)){
|
while(lexc(s)){
|
||||||
while(lex_is_whitespace(lexc(s)))
|
while(lex_is_whitespace(lexc(s)))
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
|
|
||||||
Token t = {0};
|
Token t = {0};
|
||||||
t.str = lexcp(s);
|
t.str = lexcp(s);
|
||||||
t.file = s->file;
|
t.file = s->file;
|
||||||
t.line = s->line;
|
t.line = s->line;
|
||||||
t.line_begin = s->line_begin;
|
t.line_begin = s->line_begin;
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
|
|
||||||
switch(*t.str){
|
switch(*t.str){
|
||||||
case 0: break;
|
case 0: break;
|
||||||
case '@': t.kind = TK_At; break;
|
case '@': t.kind = TK_At; break;
|
||||||
@@ -324,7 +324,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
case ';': t.kind = TK_Semicolon; break;
|
case ';': t.kind = TK_Semicolon; break;
|
||||||
case '#': t.kind = TK_Pound; break;
|
case '#': t.kind = TK_Pound; break;
|
||||||
CASE2('!', TK_Not, TK_NotEquals);
|
CASE2('!', TK_Not, TK_NotEquals);
|
||||||
CASE2('^', TK_BitXor, TK_XorAssign);
|
CASE2('^', TK_Pointer, TK_XorAssign);
|
||||||
CASE2('=', TK_Assign, TK_Equals);
|
CASE2('=', TK_Assign, TK_Equals);
|
||||||
CASE2('*', TK_Mul, TK_MulAssign);
|
CASE2('*', TK_Mul, TK_MulAssign);
|
||||||
CASE2('%', TK_Mod, TK_ModAssign);
|
CASE2('%', TK_Mod, TK_ModAssign);
|
||||||
@@ -342,8 +342,8 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
t.kind = TK_Dot;
|
t.kind = TK_Dot;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
||||||
case '<': {
|
case '<': {
|
||||||
if (lexc(s) == '<') {
|
if (lexc(s) == '<') {
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
@@ -363,7 +363,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
t.kind = TK_LesserThen;
|
t.kind = TK_LesserThen;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case '>': {
|
case '>': {
|
||||||
if (lexc(s) == '>') {
|
if (lexc(s) == '>') {
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
@@ -383,7 +383,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
t.kind = TK_GreaterThen;
|
t.kind = TK_GreaterThen;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ':': {
|
case ':': {
|
||||||
if (lexc(s) == ':') {
|
if (lexc(s) == ':') {
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
@@ -397,7 +397,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
t.kind = TK_Colon;
|
t.kind = TK_Colon;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case '-':{
|
case '-':{
|
||||||
if (lexc(s) == '=') {
|
if (lexc(s) == '=') {
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
@@ -415,11 +415,11 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
t.kind = TK_Sub;
|
t.kind = TK_Sub;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
||||||
case '\'':{not_implemented;} break;
|
case '\'':{not_implemented;} break;
|
||||||
case '"': {
|
case '"': {
|
||||||
t.kind = TK_StringLit;
|
t.kind = TK_StringLit;
|
||||||
lex_parse_string(s,&t,'"');
|
lex_parse_string(s,&t,'"');
|
||||||
if(t.kind != TK_Error){
|
if(t.kind != TK_Error){
|
||||||
t.str += 1;
|
t.str += 1;
|
||||||
@@ -427,7 +427,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
}
|
}
|
||||||
t.intern_val = intern_string(&array->interns, t.string);
|
t.intern_val = intern_string(&array->interns, t.string);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case '/': {
|
case '/': {
|
||||||
if(lexc(s) == '='){
|
if(lexc(s) == '='){
|
||||||
t.kind = TK_DivAssign;
|
t.kind = TK_DivAssign;
|
||||||
@@ -464,7 +464,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
t.kind = TK_Div;
|
t.kind = TK_Div;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case '0':case '1':case '2':case '3':case '4':
|
case '0':case '1':case '2':case '3':case '4':
|
||||||
case '5':case '6':case '7':case '8':case '9':{
|
case '5':case '6':case '7':case '8':case '9':{
|
||||||
t.kind = TK_Integer;
|
t.kind = TK_Integer;
|
||||||
@@ -473,7 +473,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
lex_set_len(s, &t);
|
lex_set_len(s, &t);
|
||||||
lex_parse_u64(&t);
|
lex_parse_u64(&t);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case 'A':case 'a':case 'M':case 'm':case 'B':
|
case 'A':case 'a':case 'M':case 'm':case 'B':
|
||||||
case 'b':case 'N':case 'n':case 'C':case 'c':case 'O':
|
case 'b':case 'N':case 'n':case 'C':case 'c':case 'O':
|
||||||
case 'o':case 'D':case 'd':case 'P':case 'p':case 'E':
|
case 'o':case 'D':case 'd':case 'P':case 'p':case 'E':
|
||||||
@@ -492,15 +492,15 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
t.kind = TK_Keyword;
|
t.kind = TK_Keyword;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
token_error(&t, lit("Unknown token"));
|
token_error(&t, lit("Unknown token"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(t.len==0)
|
if(t.len==0)
|
||||||
lex_set_len(s,&t);
|
lex_set_len(s,&t);
|
||||||
|
|
||||||
token_array_push(array, &t);
|
token_array_push(array, &t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -538,13 +538,13 @@ lex_test(){
|
|||||||
"\"Test_Meme\"+=-===42524 4294967295 18446744073709551615"
|
"\"Test_Meme\"+=-===42524 4294967295 18446744073709551615"
|
||||||
"for if while switch :=");
|
"for if while switch :=");
|
||||||
Token_Array array = lex_stream(scratch, test, lit("Test1"));
|
Token_Array array = lex_stream(scratch, test, lit("Test1"));
|
||||||
|
|
||||||
Token_Kind kind[] = {
|
Token_Kind kind[] = {
|
||||||
TK_Error,TK_OpenBrace,TK_CloseBrace,TK_CloseParen,TK_OpenParen,
|
TK_Error,TK_OpenBrace,TK_CloseBrace,TK_CloseParen,TK_OpenParen,
|
||||||
TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub,TK_Semicolon,
|
TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub,TK_Semicolon,
|
||||||
TK_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon,
|
TK_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon,
|
||||||
TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign,
|
TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign,
|
||||||
TK_Equals, TK_Integer, TK_Integer, TK_Integer, TK_Keyword, TK_Keyword,
|
TK_Equals, TK_Integer, TK_Integer, TK_Integer, TK_Keyword, TK_Keyword,
|
||||||
TK_Keyword, TK_Keyword, TK_ColonAssign, TK_End
|
TK_Keyword, TK_Keyword, TK_ColonAssign, TK_End
|
||||||
};
|
};
|
||||||
String strs[] = {
|
String strs[] = {
|
||||||
@@ -558,7 +558,7 @@ lex_test(){
|
|||||||
U64 vals[] = {
|
U64 vals[] = {
|
||||||
42524, 4294967295, 18446744073709551615llu
|
42524, 4294967295, 18446744073709551615llu
|
||||||
};
|
};
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int ui = 0;
|
int ui = 0;
|
||||||
for(Token *t = token_array_iter_begin(&array); t->kind != TK_End; t = token_array_iter_next(&array)){
|
for(Token *t = token_array_iter_begin(&array); t->kind != TK_End; t = token_array_iter_next(&array)){
|
||||||
@@ -569,7 +569,7 @@ lex_test(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
arena_end_scratch();
|
arena_end_scratch();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -584,7 +584,7 @@ global const char *token_kind_string[] = {
|
|||||||
[TK_Mod] = "%",
|
[TK_Mod] = "%",
|
||||||
[TK_BitAnd] = "&",
|
[TK_BitAnd] = "&",
|
||||||
[TK_BitOr] = "|",
|
[TK_BitOr] = "|",
|
||||||
[TK_BitXor] = "^",
|
[TK_Pointer] = "^",
|
||||||
[TK_Neg] = "~",
|
[TK_Neg] = "~",
|
||||||
[TK_Not] = "!",
|
[TK_Not] = "!",
|
||||||
[TK_OpenParen] = "(",
|
[TK_OpenParen] = "(",
|
||||||
|
|||||||
7
main.cpp
7
main.cpp
@@ -5,21 +5,20 @@
|
|||||||
#include "new_parse.cpp"
|
#include "new_parse.cpp"
|
||||||
#include "new_type.cpp"
|
#include "new_type.cpp"
|
||||||
#include "new_resolve.cpp"
|
#include "new_resolve.cpp"
|
||||||
|
#include "cgenerate.cpp"
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
test_os_memory();
|
test_os_memory();
|
||||||
thread_ctx_init();
|
thread_ctx_init();
|
||||||
|
test_gen();
|
||||||
test_unicode();
|
test_unicode();
|
||||||
test_resolve();
|
test_resolve();
|
||||||
test_types();
|
test_types();
|
||||||
test_parse_expr();
|
test_parse_expr();
|
||||||
|
|
||||||
map_test();
|
map_test();
|
||||||
test_array();
|
test_array();
|
||||||
test_string_builder();
|
test_string_builder();
|
||||||
test_intern_table();
|
test_intern_table();
|
||||||
lex_test();
|
lex_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
50
new_ast.cpp
50
new_ast.cpp
@@ -4,7 +4,7 @@
|
|||||||
//
|
//
|
||||||
// Parser::ast_arena - arena for asts
|
// Parser::ast_arena - arena for asts
|
||||||
// Lexer::interns::string_allocator - arena for interns
|
// Lexer::interns::string_allocator - arena for interns
|
||||||
//
|
//
|
||||||
Intern_String keyword_struct;
|
Intern_String keyword_struct;
|
||||||
Intern_String keyword_union;
|
Intern_String keyword_union;
|
||||||
Intern_String keyword_cast;
|
Intern_String keyword_cast;
|
||||||
@@ -19,21 +19,25 @@ const U64 Parse_Ctx_ID = 115151;
|
|||||||
struct Parse_Ctx:Lexer{
|
struct Parse_Ctx:Lexer{
|
||||||
Allocator *perm; // Stores: AST, tokens, interns
|
Allocator *perm; // Stores: AST, tokens, interns
|
||||||
Allocator *heap;
|
Allocator *heap;
|
||||||
|
|
||||||
U64 unique_ids;
|
U64 unique_ids;
|
||||||
Map global_syms;
|
Map global_syms;
|
||||||
Map type_map;
|
Map type_map;
|
||||||
|
|
||||||
Token empty_token;
|
Token empty_token;
|
||||||
S64 indent;
|
S64 indent;
|
||||||
|
|
||||||
|
Intern_String intern(String string){
|
||||||
|
return intern_string(&interns, string);
|
||||||
|
}
|
||||||
|
|
||||||
void init(Allocator *perm_allocator, Allocator *heap_allocator){
|
void init(Allocator *perm_allocator, Allocator *heap_allocator){
|
||||||
perm = perm_allocator;
|
perm = perm_allocator;
|
||||||
heap = heap_allocator;
|
heap = heap_allocator;
|
||||||
|
|
||||||
global_syms = {heap};
|
global_syms = {heap};
|
||||||
type_map = {heap};
|
type_map = {heap};
|
||||||
|
|
||||||
lex_init(perm, heap, this);
|
lex_init(perm, heap, this);
|
||||||
keyword_struct= intern_string(&interns, "struct"_s);
|
keyword_struct= intern_string(&interns, "struct"_s);
|
||||||
keyword_union = intern_string(&interns, "union"_s);
|
keyword_union = intern_string(&interns, "union"_s);
|
||||||
@@ -41,7 +45,7 @@ struct Parse_Ctx:Lexer{
|
|||||||
keyword_enum = intern_string(&interns, "enum"_s);
|
keyword_enum = intern_string(&interns, "enum"_s);
|
||||||
interns.first_keyword = keyword_struct.str;
|
interns.first_keyword = keyword_struct.str;
|
||||||
interns.last_keyword = keyword_enum.str;
|
interns.last_keyword = keyword_enum.str;
|
||||||
|
|
||||||
intern_void = intern_string(&interns, "void"_s);
|
intern_void = intern_string(&interns, "void"_s);
|
||||||
intern_int = intern_string(&interns, "int"_s);
|
intern_int = intern_string(&interns, "int"_s);
|
||||||
intern_str = intern_string(&interns, "String"_s);
|
intern_str = intern_string(&interns, "String"_s);
|
||||||
@@ -55,9 +59,9 @@ thread_local Parse_Ctx *pctx;
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
enum Ast_Kind{
|
enum Ast_Kind{
|
||||||
AST_NONE,
|
AST_NONE,
|
||||||
|
|
||||||
AST_PACKAGE,
|
AST_PACKAGE,
|
||||||
|
|
||||||
AST_STR,
|
AST_STR,
|
||||||
AST_INT,
|
AST_INT,
|
||||||
AST_CAST,
|
AST_CAST,
|
||||||
@@ -67,12 +71,12 @@ enum Ast_Kind{
|
|||||||
AST_BINARY,
|
AST_BINARY,
|
||||||
AST_COMPOUND_ITEM,
|
AST_COMPOUND_ITEM,
|
||||||
AST_COMPOUND,
|
AST_COMPOUND,
|
||||||
|
|
||||||
AST_LAMBDA,
|
AST_LAMBDA,
|
||||||
AST_LAMBDA_PARAM,
|
AST_LAMBDA_PARAM,
|
||||||
AST_CONST,
|
AST_CONST,
|
||||||
AST_VAR,
|
AST_VAR,
|
||||||
|
|
||||||
AST_TYPESPEC_IDENT,
|
AST_TYPESPEC_IDENT,
|
||||||
AST_TYPESPEC_POINTER,
|
AST_TYPESPEC_POINTER,
|
||||||
AST_TYPESPEC_ARRAY,
|
AST_TYPESPEC_ARRAY,
|
||||||
@@ -85,6 +89,7 @@ struct Ast{
|
|||||||
Token *pos;
|
Token *pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Ast_Resolved_Type;
|
||||||
struct Ast_Typespec;
|
struct Ast_Typespec;
|
||||||
struct Ast_Expr:Ast{
|
struct Ast_Expr:Ast{
|
||||||
union{
|
union{
|
||||||
@@ -94,13 +99,13 @@ struct Ast_Expr:Ast{
|
|||||||
Token_Kind op;
|
Token_Kind op;
|
||||||
Ast_Expr *expr;
|
Ast_Expr *expr;
|
||||||
}unary;
|
}unary;
|
||||||
|
|
||||||
struct{
|
struct{
|
||||||
Token_Kind op;
|
Token_Kind op;
|
||||||
Ast_Expr *left;
|
Ast_Expr *left;
|
||||||
Ast_Expr *right;
|
Ast_Expr *right;
|
||||||
} binary;
|
} binary;
|
||||||
struct{
|
struct{
|
||||||
|
Ast_Resolved_Type *type;
|
||||||
Ast_Typespec *typespec;
|
Ast_Typespec *typespec;
|
||||||
Array<Ast_Expr *> exprs;
|
Array<Ast_Expr *> exprs;
|
||||||
}compound;
|
}compound;
|
||||||
@@ -124,12 +129,19 @@ struct Ast_Expr:Ast{
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Ast_Block : Ast {
|
||||||
|
Array<Ast *> stmts;
|
||||||
|
};
|
||||||
|
|
||||||
struct Ast_Lambda : Ast_Expr {
|
struct Ast_Lambda : Ast_Expr {
|
||||||
Array<Ast_Expr *> params;
|
Array<Ast_Expr *> params;
|
||||||
Ast_Typespec *ret;
|
Ast_Typespec *ret;
|
||||||
|
Ast_Block *block;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Ast_Resolved_Type;
|
||||||
struct Ast_Typespec:Ast{
|
struct Ast_Typespec:Ast{
|
||||||
|
Ast_Resolved_Type *resolved_type;
|
||||||
union{
|
union{
|
||||||
Ast_Typespec *base;
|
Ast_Typespec *base;
|
||||||
Intern_String name;
|
Intern_String name;
|
||||||
@@ -148,10 +160,6 @@ struct Ast_Decl:Ast{
|
|||||||
Ast_Typespec *typespec;
|
Ast_Typespec *typespec;
|
||||||
Ast_Expr *expr;
|
Ast_Expr *expr;
|
||||||
}var;
|
}var;
|
||||||
struct{
|
|
||||||
Array<Ast_Decl*> args;
|
|
||||||
Ast_Typespec *ret;
|
|
||||||
}func;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -164,10 +172,10 @@ struct Ast_Package:Ast{
|
|||||||
// AST Constructors beginning with expressions
|
// AST Constructors beginning with expressions
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#define AST_NEW(T,ikind,ipos) \
|
#define AST_NEW(T,ikind,ipos) \
|
||||||
Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \
|
Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \
|
||||||
result->kind = ikind; \
|
result->kind = ikind; \
|
||||||
result->pos = ipos; \
|
result->pos = ipos; \
|
||||||
result->id = ++pctx->unique_ids
|
result->id = ++pctx->unique_ids
|
||||||
|
|
||||||
function Ast_Expr *
|
function Ast_Expr *
|
||||||
ast_expr_string(Token *pos, Intern_String string){
|
ast_expr_string(Token *pos, Intern_String string){
|
||||||
@@ -327,4 +335,4 @@ ast_package(Token *pos, String name, Array<Ast_Decl *> decls){
|
|||||||
result->decls = decls.tight_copy(pctx->perm);
|
result->decls = decls.tight_copy(pctx->perm);
|
||||||
result->name = intern_string(&pctx->interns, name);
|
result->name = intern_string(&pctx->interns, name);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
152
new_lex.cpp
152
new_lex.cpp
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
enum Token_Kind{
|
enum Token_Kind{
|
||||||
TK_End,
|
TK_End,
|
||||||
|
|
||||||
TK_Mul,
|
TK_Mul,
|
||||||
TK_Div,
|
TK_Div,
|
||||||
TK_Mod,
|
TK_Mod,
|
||||||
@@ -9,12 +9,12 @@ enum Token_Kind{
|
|||||||
TK_RightShift,
|
TK_RightShift,
|
||||||
TK_FirstMul = TK_Mul,
|
TK_FirstMul = TK_Mul,
|
||||||
TK_LastMul = TK_RightShift,
|
TK_LastMul = TK_RightShift,
|
||||||
|
|
||||||
TK_Add,
|
TK_Add,
|
||||||
TK_Sub,
|
TK_Sub,
|
||||||
TK_FirstAdd = TK_Add,
|
TK_FirstAdd = TK_Add,
|
||||||
TK_LastAdd = TK_Sub,
|
TK_LastAdd = TK_Sub,
|
||||||
|
|
||||||
TK_Equals,
|
TK_Equals,
|
||||||
TK_LesserThenOrEqual,
|
TK_LesserThenOrEqual,
|
||||||
TK_GreaterThenOrEqual,
|
TK_GreaterThenOrEqual,
|
||||||
@@ -23,15 +23,14 @@ enum Token_Kind{
|
|||||||
TK_NotEquals,
|
TK_NotEquals,
|
||||||
TK_FirstCompare = TK_Equals,
|
TK_FirstCompare = TK_Equals,
|
||||||
TK_LastCompare = TK_NotEquals,
|
TK_LastCompare = TK_NotEquals,
|
||||||
|
|
||||||
TK_BitAnd,
|
TK_BitAnd,
|
||||||
TK_BitOr,
|
TK_BitOr,
|
||||||
TK_BitXor,
|
|
||||||
TK_And,
|
TK_And,
|
||||||
TK_Or,
|
TK_Or,
|
||||||
TK_FirstLogical = TK_BitAnd,
|
TK_FirstLogical = TK_BitAnd,
|
||||||
TK_LastLogical = TK_Or,
|
TK_LastLogical = TK_Or,
|
||||||
|
|
||||||
TK_Neg,
|
TK_Neg,
|
||||||
TK_Not,
|
TK_Not,
|
||||||
TK_OpenParen,
|
TK_OpenParen,
|
||||||
@@ -46,10 +45,10 @@ enum Token_Kind{
|
|||||||
TK_ThreeDots,
|
TK_ThreeDots,
|
||||||
TK_Semicolon,
|
TK_Semicolon,
|
||||||
TK_Dot,
|
TK_Dot,
|
||||||
|
|
||||||
TK_NewLine,
|
TK_NewLine,
|
||||||
TK_Colon,
|
TK_Colon,
|
||||||
|
|
||||||
TK_Assign,
|
TK_Assign,
|
||||||
TK_DivAssign,
|
TK_DivAssign,
|
||||||
TK_MulAssign,
|
TK_MulAssign,
|
||||||
@@ -63,14 +62,14 @@ enum Token_Kind{
|
|||||||
TK_RightShiftAssign,
|
TK_RightShiftAssign,
|
||||||
TK_FirstAssign = TK_Assign,
|
TK_FirstAssign = TK_Assign,
|
||||||
TK_LastAssign = TK_RightShiftAssign,
|
TK_LastAssign = TK_RightShiftAssign,
|
||||||
|
|
||||||
TK_DoubleColon,
|
TK_DoubleColon,
|
||||||
TK_At,
|
TK_At,
|
||||||
TK_Decrement,
|
TK_Decrement,
|
||||||
TK_Increment,
|
TK_Increment,
|
||||||
TK_PostDecrement,
|
TK_PostDecrement,
|
||||||
TK_PostIncrement,
|
TK_PostIncrement,
|
||||||
|
|
||||||
TK_Arrow,
|
TK_Arrow,
|
||||||
TK_ExprSizeof,
|
TK_ExprSizeof,
|
||||||
TK_DocComment,
|
TK_DocComment,
|
||||||
@@ -82,8 +81,8 @@ enum Token_Kind{
|
|||||||
TK_Float,
|
TK_Float,
|
||||||
TK_Integer,
|
TK_Integer,
|
||||||
TK_Keyword,
|
TK_Keyword,
|
||||||
|
|
||||||
TK_Pointer = TK_BitXor,
|
TK_Pointer,
|
||||||
TK_Dereference,
|
TK_Dereference,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -93,7 +92,7 @@ struct Token{
|
|||||||
String string;
|
String string;
|
||||||
struct{U8 *str; S64 len;};
|
struct{U8 *str; S64 len;};
|
||||||
};
|
};
|
||||||
|
|
||||||
union {
|
union {
|
||||||
U64 int_val;
|
U64 int_val;
|
||||||
F64 float_val;
|
F64 float_val;
|
||||||
@@ -101,7 +100,7 @@ struct Token{
|
|||||||
Intern_String intern_val;
|
Intern_String intern_val;
|
||||||
S64 indent;
|
S64 indent;
|
||||||
};
|
};
|
||||||
|
|
||||||
String file;
|
String file;
|
||||||
S32 line;
|
S32 line;
|
||||||
U8 *line_begin;
|
U8 *line_begin;
|
||||||
@@ -110,7 +109,7 @@ struct Token{
|
|||||||
struct Lex_Stream{
|
struct Lex_Stream{
|
||||||
String stream;
|
String stream;
|
||||||
S64 iter;
|
S64 iter;
|
||||||
|
|
||||||
U8 *line_begin;
|
U8 *line_begin;
|
||||||
String file;
|
String file;
|
||||||
S32 line;
|
S32 line;
|
||||||
@@ -157,7 +156,7 @@ lex_is_numeric(U8 c){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function B32
|
function B32
|
||||||
lex_is_alphanumeric(U8 c){
|
lex_is_alphanumeric(U8 c){
|
||||||
B32 result = lex_is_numeric(c) || lex_is_alphabetic(c);
|
B32 result = lex_is_numeric(c) || lex_is_alphabetic(c);
|
||||||
return result;
|
return result;
|
||||||
@@ -172,9 +171,9 @@ lex_set_len(Lex_Stream *s, Token *token){
|
|||||||
function void
|
function void
|
||||||
lex_set_keywords(Lexer *lexer, Array<String> keywords){
|
lex_set_keywords(Lexer *lexer, Array<String> keywords){
|
||||||
Intern_String keyword = {};
|
Intern_String keyword = {};
|
||||||
Iter(keywords){
|
For(keywords){
|
||||||
keyword = intern_string(&lexer->interns, *it);
|
keyword = intern_string(&lexer->interns, *it);
|
||||||
if(it == keywords.begin())
|
if(it == keywords.begin())
|
||||||
lexer->interns.first_keyword = keyword.str;
|
lexer->interns.first_keyword = keyword.str;
|
||||||
}
|
}
|
||||||
lexer->interns.last_keyword = keyword.str;
|
lexer->interns.last_keyword = keyword.str;
|
||||||
@@ -193,7 +192,7 @@ token_error(Token *t, String error_val){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
lex_parse_u64(Token *t){
|
lex_parse_u64(Token *t){
|
||||||
U64 result = 0;
|
U64 result = 0;
|
||||||
U64 m = 1;
|
U64 m = 1;
|
||||||
for(S64 i = t->len - 1; i >= 0; --i){
|
for(S64 i = t->len - 1; i >= 0; --i){
|
||||||
@@ -224,7 +223,7 @@ lex_advance(Lex_Stream *s){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
lex_parse_string(Lex_Stream *s, Token *t, U8 c){
|
lex_parse_string(Lex_Stream *s, Token *t, U8 c){
|
||||||
for(;;){
|
for(;;){
|
||||||
if(lexc(s) == '\\') lex_advance(s);
|
if(lexc(s) == '\\') lex_advance(s);
|
||||||
@@ -241,39 +240,39 @@ lex_parse_string(Lex_Stream *s, Token *t, U8 c){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CASE2(op, OpName, Assign) \
|
#define CASE2(op, OpName, Assign) \
|
||||||
case op: \
|
case op: \
|
||||||
if (lexc(s) == '=') { \
|
if (lexc(s) == '=') { \
|
||||||
lex_advance(s); \
|
lex_advance(s); \
|
||||||
t.kind = Assign; \
|
t.kind = Assign; \
|
||||||
} else { \
|
} else { \
|
||||||
t.kind = OpName; \
|
t.kind = OpName; \
|
||||||
} \
|
} \
|
||||||
break
|
break
|
||||||
#define CASE3(op, OpName, Assign, Incr) \
|
#define CASE3(op, OpName, Assign, Incr) \
|
||||||
case op: \
|
case op: \
|
||||||
if (lexc(s) == '=') { \
|
if (lexc(s) == '=') { \
|
||||||
lex_advance(s); \
|
lex_advance(s); \
|
||||||
t.kind = Assign; \
|
t.kind = Assign; \
|
||||||
} else if (lexc(s) == op) { \
|
} else if (lexc(s) == op) { \
|
||||||
lex_advance(s); \
|
lex_advance(s); \
|
||||||
t.kind = Incr; \
|
t.kind = Incr; \
|
||||||
} else { \
|
} else { \
|
||||||
t.kind = OpName; \
|
t.kind = OpName; \
|
||||||
} \
|
} \
|
||||||
break
|
break
|
||||||
|
|
||||||
function void
|
function void
|
||||||
lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||||
while(lexc(s)){
|
while(lexc(s)){
|
||||||
|
|
||||||
Token t = {};
|
Token t = {};
|
||||||
t.str = lexcp(s);
|
t.str = lexcp(s);
|
||||||
t.file = s->file;
|
t.file = s->file;
|
||||||
t.line = s->line;
|
t.line = s->line;
|
||||||
t.line_begin = s->line_begin;
|
t.line_begin = s->line_begin;
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
|
|
||||||
switch(*t.str){
|
switch(*t.str){
|
||||||
case 0 : break;
|
case 0 : break;
|
||||||
case '@': t.kind = TK_At; break;
|
case '@': t.kind = TK_At; break;
|
||||||
@@ -287,8 +286,8 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
case '~': t.kind = TK_Neg; break;
|
case '~': t.kind = TK_Neg; break;
|
||||||
case '?': t.kind = TK_Question; break;
|
case '?': t.kind = TK_Question; break;
|
||||||
case '#': t.kind = TK_Pound; break;
|
case '#': t.kind = TK_Pound; break;
|
||||||
|
case '^': t.kind = TK_Pointer; break;
|
||||||
CASE2('!', TK_Not, TK_NotEquals);
|
CASE2('!', TK_Not, TK_NotEquals);
|
||||||
CASE2('^', TK_BitXor, TK_XorAssign);
|
|
||||||
CASE2('=', TK_Assign, TK_Equals);
|
CASE2('=', TK_Assign, TK_Equals);
|
||||||
CASE2('*', TK_Mul, TK_MulAssign);
|
CASE2('*', TK_Mul, TK_MulAssign);
|
||||||
CASE2('%', TK_Mod, TK_ModAssign);
|
CASE2('%', TK_Mod, TK_ModAssign);
|
||||||
@@ -298,15 +297,15 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
#undef CASE2
|
#undef CASE2
|
||||||
#undef CASE3
|
#undef CASE3
|
||||||
case ';': {
|
case ';': {
|
||||||
t.kind = TK_Semicolon;
|
t.kind = TK_Semicolon;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case ' ' : s->stream.str -= 1;
|
case ' ' : s->stream.str -= 1;
|
||||||
case '\n': {
|
case '\n': {
|
||||||
t.kind = TK_NewLine;
|
t.kind = TK_NewLine;
|
||||||
if(lexc(s) == '\r')
|
if(lexc(s) == '\r')
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
if(lexc(s) == ' ') {
|
if(lexc(s) == ' ') {
|
||||||
t.indent++;
|
t.indent++;
|
||||||
@@ -316,7 +315,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
else break;
|
else break;
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
}break;
|
}break;
|
||||||
case '.': {
|
case '.': {
|
||||||
if(lexc(s) == '.' && lexci(s,1) == '.') {
|
if(lexc(s) == '.' && lexci(s,1) == '.') {
|
||||||
@@ -327,8 +326,8 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
t.kind = TK_Dot;
|
t.kind = TK_Dot;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
||||||
case '<': {
|
case '<': {
|
||||||
if (lexc(s) == '<') {
|
if (lexc(s) == '<') {
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
@@ -348,7 +347,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
t.kind = TK_LesserThen;
|
t.kind = TK_LesserThen;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case '>': {
|
case '>': {
|
||||||
if (lexc(s) == '>') {
|
if (lexc(s) == '>') {
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
@@ -368,7 +367,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
t.kind = TK_GreaterThen;
|
t.kind = TK_GreaterThen;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ':': {
|
case ':': {
|
||||||
if (lexc(s) == ':') {
|
if (lexc(s) == ':') {
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
@@ -378,7 +377,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
t.kind = TK_Colon;
|
t.kind = TK_Colon;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case '-':{
|
case '-':{
|
||||||
if (lexc(s) == '=') {
|
if (lexc(s) == '=') {
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
@@ -396,11 +395,11 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
t.kind = TK_Sub;
|
t.kind = TK_Sub;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
||||||
case '\'':{not_implemented;} break;
|
case '\'':{not_implemented;} break;
|
||||||
case '"': {
|
case '"': {
|
||||||
t.kind = TK_StringLit;
|
t.kind = TK_StringLit;
|
||||||
lex_parse_string(s,&t,'"');
|
lex_parse_string(s,&t,'"');
|
||||||
if(t.kind != TK_Error){
|
if(t.kind != TK_Error){
|
||||||
t.str += 1;
|
t.str += 1;
|
||||||
@@ -408,7 +407,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
}
|
}
|
||||||
t.intern_val = intern_string(table, t.string);
|
t.intern_val = intern_string(table, t.string);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case '/': {
|
case '/': {
|
||||||
if(lexc(s) == '='){
|
if(lexc(s) == '='){
|
||||||
t.kind = TK_DivAssign;
|
t.kind = TK_DivAssign;
|
||||||
@@ -445,7 +444,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
t.kind = TK_Div;
|
t.kind = TK_Div;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case '0':case '1':case '2':case '3':case '4':
|
case '0':case '1':case '2':case '3':case '4':
|
||||||
case '5':case '6':case '7':case '8':case '9':{
|
case '5':case '6':case '7':case '8':case '9':{
|
||||||
t.kind = TK_Integer;
|
t.kind = TK_Integer;
|
||||||
@@ -454,7 +453,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
lex_set_len(s, &t);
|
lex_set_len(s, &t);
|
||||||
lex_parse_u64(&t);
|
lex_parse_u64(&t);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case 'A':case 'a':case 'M':case 'm':case 'B':
|
case 'A':case 'a':case 'M':case 'm':case 'B':
|
||||||
case 'b':case 'N':case 'n':case 'C':case 'c':case 'O':
|
case 'b':case 'N':case 'n':case 'C':case 'c':case 'O':
|
||||||
case 'o':case 'D':case 'd':case 'P':case 'p':case 'E':
|
case 'o':case 'D':case 'd':case 'P':case 'p':case 'E':
|
||||||
@@ -473,23 +472,23 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
t.kind = TK_Keyword;
|
t.kind = TK_Keyword;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
token_error(&t, "Unknown token"_s);
|
token_error(&t, "Unknown token"_s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(t.len==0)
|
if(t.len==0)
|
||||||
lex_set_len(s,&t);
|
lex_set_len(s,&t);
|
||||||
|
|
||||||
B32 skip = t.kind == TK_NewLine && s->inside_brace_paren > 0;
|
B32 skip = t.kind == TK_NewLine && s->inside_brace_paren > 0;
|
||||||
if(!skip){
|
if(!skip){
|
||||||
array->add(t);
|
array->add(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(lex_is_whitespace(lexc(s)))
|
while(lex_is_whitespace(lexc(s)))
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
|
|
||||||
if(s->iter >= s->stream.len) // End of stream
|
if(s->iter >= s->stream.len) // End of stream
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -510,7 +509,12 @@ lex_make(Allocator *token_string_arena, Allocator *map_allocator){
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
lex_restream(Lexer *lexer, String istream, String file){
|
lex_restream(Lexer *lexer, String istream, String file){
|
||||||
lexer->stream = {istream, 0, istream.str, file, 0};
|
lexer->stream = {};
|
||||||
|
lexer->stream.stream = istream;
|
||||||
|
lexer->stream.line_begin = istream.str;
|
||||||
|
lexer->stream.file = file;
|
||||||
|
|
||||||
|
|
||||||
lexer->tokens.clear();
|
lexer->tokens.clear();
|
||||||
lexer->token_iter = 0;
|
lexer->token_iter = 0;
|
||||||
lex__stream(&lexer->interns, &lexer->tokens, &lexer->stream);
|
lex__stream(&lexer->interns, &lexer->tokens, &lexer->stream);
|
||||||
@@ -529,26 +533,26 @@ lex_test(){
|
|||||||
String test = "Keyword //R\n 18446744073709551616{})(@?&+-;....->,:::/**/\"Thing\" Thingy"
|
String test = "Keyword //R\n 18446744073709551616{})(@?&+-;....->,:::/**/\"Thing\" Thingy"
|
||||||
"\"Test_Meme\"+=-===42524 4294967295 18446744073709551615"
|
"\"Test_Meme\"+=-===42524 4294967295 18446744073709551615"
|
||||||
"for if while switch :="_s;
|
"for if while switch :="_s;
|
||||||
|
|
||||||
Array<String> keywords = {scratch};
|
Array<String> keywords = {scratch};
|
||||||
keywords.add("Keyword"_s);
|
keywords.add("Keyword"_s);
|
||||||
keywords.add("for"_s);
|
keywords.add("for"_s);
|
||||||
keywords.add("if"_s);
|
keywords.add("if"_s);
|
||||||
keywords.add("while"_s);
|
keywords.add("while"_s);
|
||||||
keywords.add("switch"_s);
|
keywords.add("switch"_s);
|
||||||
|
|
||||||
Lexer lexer = lex_make(scratch, scratch);
|
Lexer lexer = lex_make(scratch, scratch);
|
||||||
lex_set_keywords(&lexer, keywords);
|
lex_set_keywords(&lexer, keywords);
|
||||||
lex_restream(&lexer, test, "Test1"_s);
|
lex_restream(&lexer, test, "Test1"_s);
|
||||||
Array<Token> arr = lexer.tokens;
|
Array<Token> arr = lexer.tokens;
|
||||||
|
|
||||||
Token_Kind kind[] = {
|
Token_Kind kind[] = {
|
||||||
TK_Keyword, TK_NewLine, TK_Error,TK_OpenBrace,TK_CloseBrace,TK_CloseParen,TK_OpenParen,
|
TK_Keyword, TK_NewLine, TK_Error,TK_OpenBrace,TK_CloseBrace,TK_CloseParen,TK_OpenParen,
|
||||||
TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub,TK_Semicolon,
|
TK_At,TK_Question,TK_BitAnd,TK_Add,TK_Sub,TK_Semicolon,
|
||||||
TK_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon,
|
TK_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon,
|
||||||
TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign,
|
TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign,
|
||||||
TK_Equals, TK_Integer, TK_Integer, TK_Integer,
|
TK_Equals, TK_Integer, TK_Integer, TK_Integer,
|
||||||
TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword,
|
TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword,
|
||||||
TK_Colon, TK_Assign, TK_End
|
TK_Colon, TK_Assign, TK_End
|
||||||
};
|
};
|
||||||
String strs[] = {
|
String strs[] = {
|
||||||
@@ -562,7 +566,7 @@ lex_test(){
|
|||||||
U64 vals[] = {
|
U64 vals[] = {
|
||||||
42524, 4294967295, 18446744073709551615llu
|
42524, 4294967295, 18446744073709551615llu
|
||||||
};
|
};
|
||||||
|
|
||||||
int ui = 0;
|
int ui = 0;
|
||||||
For(arr){
|
For(arr){
|
||||||
assert(it->kind == kind[i]);
|
assert(it->kind == kind[i]);
|
||||||
@@ -576,7 +580,7 @@ lex_test(){
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Token metadata
|
// Token metadata
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
function String
|
function String
|
||||||
token_kind_string(Token_Kind kind){
|
token_kind_string(Token_Kind kind){
|
||||||
switch(kind){
|
switch(kind){
|
||||||
case TK_End: return "End of stream"_s;
|
case TK_End: return "End of stream"_s;
|
||||||
@@ -587,7 +591,7 @@ token_kind_string(Token_Kind kind){
|
|||||||
case TK_Mod: return "%"_s;
|
case TK_Mod: return "%"_s;
|
||||||
case TK_BitAnd: return "&"_s;
|
case TK_BitAnd: return "&"_s;
|
||||||
case TK_BitOr: return "|"_s;
|
case TK_BitOr: return "|"_s;
|
||||||
case TK_BitXor: return "^"_s;
|
case TK_Pointer: return "^"_s;
|
||||||
case TK_Neg: return "~"_s;
|
case TK_Neg: return "~"_s;
|
||||||
case TK_Not: return "!"_s;
|
case TK_Not: return "!"_s;
|
||||||
case TK_OpenParen: return "("_s;
|
case TK_OpenParen: return "("_s;
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ token_get(S64 i = 0){
|
|||||||
if(result->kind == TK_NewLine){
|
if(result->kind == TK_NewLine){
|
||||||
pctx->indent = result->indent;
|
pctx->indent = result->indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Token *
|
function Token *
|
||||||
token_next(){
|
token_next(){
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
pctx->token_iter++;
|
pctx->token_iter++;
|
||||||
return token;
|
return token;
|
||||||
@@ -51,28 +51,28 @@ token_match_keyword(Intern_String string){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
parsing_error(Token *token, const char *str, ...){
|
parsing_error(Token *token, const char *str, ...){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
STRING_FMT(scratch, str, string);
|
STRING_FMT(scratch, str, string);
|
||||||
|
|
||||||
// @Note(Krzosa): Print nice error message
|
// @Note(Krzosa): Print nice error message
|
||||||
printf("\nError: %s", string.str);
|
printf("\nError: %s", string.str);
|
||||||
if(token){
|
if(token){
|
||||||
printf(" %s:%d\n", token->file.str, (S32)token->line);
|
printf(" %s:%d\n", token->file.str, (S32)token->line);
|
||||||
|
|
||||||
// @Note(Krzosa): Print error line
|
// @Note(Krzosa): Print error line
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
|
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
|
||||||
printf("%.*s\n", i, token->line_begin);
|
printf("%.*s\n", i, token->line_begin);
|
||||||
|
|
||||||
// @Note(Krzosa): Print error marker
|
// @Note(Krzosa): Print error marker
|
||||||
int token_i = token->str - token->line_begin;
|
int token_i = token->str - token->line_begin;
|
||||||
for(int i = 0; i < token_i-2; i++) printf(" ");
|
for(int i = 0; i < token_i-2; i++) printf(" ");
|
||||||
printf("^^^^^^\n");
|
printf("^^^^^^\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,15 +97,15 @@ compare = == | != | >= | > | <= | <
|
|||||||
logical = [&|^] | && | ||
|
logical = [&|^] | && | ||
|
||||||
unary = [&*-!~+] | ++ | --
|
unary = [&*-!~+] | ++ | --
|
||||||
|
|
||||||
atom_expr = Int
|
atom_expr = Int
|
||||||
| Float
|
| Float
|
||||||
| String
|
| String
|
||||||
| Identifier
|
| Identifier
|
||||||
| 'cast' '(' typespec ',' expr ')'
|
| 'cast' '(' typespec ',' expr ')'
|
||||||
| 'size_type' '(' typespec ')'
|
| 'size_type' '(' typespec ')'
|
||||||
| 'size_expr' '(' expr ')'
|
| 'size_expr' '(' expr ')'
|
||||||
| '{' compound_expr '}'
|
| '{' compound_expr '}'
|
||||||
| '(' expr ')'
|
| '(' expr ')'
|
||||||
| '(' ':' typespec ')' '{' compound_expr '}'
|
| '(' ':' typespec ')' '{' compound_expr '}'
|
||||||
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
|
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
|
||||||
unary_expr = unary ? unary_expr : atom_expr
|
unary_expr = unary ? unary_expr : atom_expr
|
||||||
@@ -143,17 +143,17 @@ parse_expr_compound(){
|
|||||||
name = ast_expr_identifier(token, token->intern_val);
|
name = ast_expr_identifier(token, token->intern_val);
|
||||||
token_expect(TK_Assign);
|
token_expect(TK_Assign);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Expr *item = parse_expr();
|
Ast_Expr *item = parse_expr();
|
||||||
Ast_Expr *item_comp = ast_expr_compound_item(token, index, name, item);
|
Ast_Expr *item_comp = ast_expr_compound_item(token, index, name, item);
|
||||||
exprs.add(item_comp);
|
exprs.add(item_comp);
|
||||||
|
|
||||||
if(!token_match(TK_Comma)){
|
if(!token_match(TK_Comma)){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token_expect(TK_CloseBrace);
|
token_expect(TK_CloseBrace);
|
||||||
|
|
||||||
Ast_Expr *result = ast_expr_compound(pos, 0, exprs);
|
Ast_Expr *result = ast_expr_compound(pos, 0, exprs);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -165,14 +165,24 @@ parse_optional_type(){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
function Ast_Block *
|
||||||
|
parse_block(){
|
||||||
|
Ast_Block *result = 0;
|
||||||
|
if(token_match(TK_NewScope)){
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
function Ast_Lambda *
|
function Ast_Lambda *
|
||||||
parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typespec is not used currently
|
parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typespec is not used currently
|
||||||
// @Todo(Krzosa): Combine this with typespec function parsing
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast_Expr *> params = {scratch};
|
Array<Ast_Expr *> params = {scratch};
|
||||||
// @Note(Krzosa): No need to guard against "()"
|
// @Note(Krzosa): No need to guard against "()"
|
||||||
// We needed to lookahead to verify it's a function
|
// We needed to lookahead to verify it's a function
|
||||||
// and this routine only fires when we have situation
|
// and this routine only fires when we have situation
|
||||||
// with at least one parameter
|
// with at least one parameter
|
||||||
for(;;){
|
for(;;){
|
||||||
Token *name = token_expect(TK_Identifier);
|
Token *name = token_expect(TK_Identifier);
|
||||||
@@ -180,12 +190,14 @@ parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typesp
|
|||||||
Ast_Typespec *typespec = parse_typespec();
|
Ast_Typespec *typespec = parse_typespec();
|
||||||
Ast_Expr *param = ast_expr_lambda_param(name, name->intern_val, typespec);
|
Ast_Expr *param = ast_expr_lambda_param(name, name->intern_val, typespec);
|
||||||
params.add(param);
|
params.add(param);
|
||||||
|
|
||||||
if(!token_match(TK_Comma)){
|
if(!token_match(TK_Comma)){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token_expect(TK_CloseParen);
|
token_expect(TK_CloseParen);
|
||||||
|
|
||||||
|
//Ast_Block *block = parse_block();
|
||||||
Ast_Lambda *result = ast_lambda(token, params, parse_optional_type());
|
Ast_Lambda *result = ast_lambda(token, params, parse_optional_type());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -196,7 +208,7 @@ null_denotation(Token *token){
|
|||||||
case TK_StringLit : return ast_expr_string(token, token->intern_val);
|
case TK_StringLit : return ast_expr_string(token, token->intern_val);
|
||||||
case TK_Identifier: return ast_expr_identifier(token, token->intern_val);
|
case TK_Identifier: return ast_expr_identifier(token, token->intern_val);
|
||||||
case TK_Integer : return ast_expr_integer(token, token->int_val);
|
case TK_Integer : return ast_expr_integer(token, token->int_val);
|
||||||
case TK_BitXor : return ast_expr_unary(token, TK_Dereference, parse_expr());
|
case TK_Pointer : return ast_expr_unary(token, TK_Dereference, parse_expr());
|
||||||
case TK_Keyword: {
|
case TK_Keyword: {
|
||||||
if(token->intern_val == keyword_cast){
|
if(token->intern_val == keyword_cast){
|
||||||
token_expect(TK_OpenParen);
|
token_expect(TK_OpenParen);
|
||||||
@@ -207,7 +219,7 @@ null_denotation(Token *token){
|
|||||||
return ast_expr_cast(token, expr, typespec);
|
return ast_expr_cast(token, expr, typespec);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str);
|
parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
@@ -216,8 +228,8 @@ null_denotation(Token *token){
|
|||||||
if(token_match(TK_CloseParen)) return ast_expr_lambda_empty(token);
|
if(token_match(TK_CloseParen)) return ast_expr_lambda_empty(token);
|
||||||
else if(token_is(TK_Identifier) && token_is(TK_Colon, 1)) return parse_lambda(token);
|
else if(token_is(TK_Identifier) && token_is(TK_Colon, 1)) return parse_lambda(token);
|
||||||
else{
|
else{
|
||||||
Ast_Expr *result = parse_expr();
|
Ast_Expr *result = parse_expr();
|
||||||
token_expect(TK_CloseParen);
|
token_expect(TK_CloseParen);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,18 +238,18 @@ null_denotation(Token *token){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function S64
|
function S64
|
||||||
left_binding_power(Token_Kind kind){
|
left_binding_power(Token_Kind kind){
|
||||||
switch(kind){
|
switch(kind){
|
||||||
case TK_Sub: case TK_Add: return 1;
|
case TK_Sub: case TK_Add: return 1;
|
||||||
case TK_Mul: case TK_Div: return 2;
|
case TK_Mul: case TK_Div: return 2;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function S64
|
function S64
|
||||||
postfix_binding_power(Token_Kind kind){
|
postfix_binding_power(Token_Kind kind){
|
||||||
switch(kind){
|
switch(kind){
|
||||||
case TK_Increment: case TK_Decrement: case TK_BitXor: case TK_OpenBracket: return 1;
|
case TK_Increment: case TK_Decrement: case TK_Pointer: case TK_OpenBracket: return 1;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,11 +271,11 @@ parse_expr(S64 rbp){
|
|||||||
Ast_Expr *left = null_denotation(token);
|
Ast_Expr *left = null_denotation(token);
|
||||||
for(;;){
|
for(;;){
|
||||||
token = token_get();
|
token = token_get();
|
||||||
|
|
||||||
if((rbp == 0) && (token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_BitXor || token->kind == TK_OpenBracket)){
|
if((rbp == 0) && (token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_Pointer || token->kind == TK_OpenBracket)){
|
||||||
token_next();
|
token_next();
|
||||||
if(token->kind == TK_OpenBracket){
|
if(token->kind == TK_OpenBracket){
|
||||||
Ast_Expr *index = parse_expr();
|
Ast_Expr *index = parse_expr();
|
||||||
left = ast_expr_index(token, left, index);
|
left = ast_expr_index(token, left, index);
|
||||||
token_expect(TK_CloseBracket);
|
token_expect(TK_CloseBracket);
|
||||||
}
|
}
|
||||||
@@ -273,13 +285,13 @@ parse_expr(S64 rbp){
|
|||||||
left = ast_expr_unary(token, token->kind, left);
|
left = ast_expr_unary(token, token->kind, left);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(rbp < left_binding_power(token->kind)){
|
else if(rbp < left_binding_power(token->kind)){
|
||||||
token = token_next();
|
token = token_next();
|
||||||
left = left_denotation(token, left);
|
left = left_denotation(token, left);
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
|
|
||||||
}
|
}
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
@@ -312,11 +324,11 @@ expr_eval(Ast_Expr *expr){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_PARSER() \
|
#define TEST_PARSER() \
|
||||||
Scratch scratch(thread_ctx.scratch);\
|
Scratch scratch(thread_ctx.scratch); \
|
||||||
Parse_Ctx ctx = {}; \
|
Parse_Ctx ctx = {}; \
|
||||||
ctx.init(scratch, scratch); \
|
ctx.init(scratch, scratch); \
|
||||||
pctx = &ctx
|
pctx = &ctx
|
||||||
|
|
||||||
function void
|
function void
|
||||||
test_parse_expr(){
|
test_parse_expr(){
|
||||||
@@ -329,8 +341,8 @@ test_parse_expr(){
|
|||||||
exprs.add({"4+5*2"_s, 4+5*2});
|
exprs.add({"4+5*2"_s, 4+5*2});
|
||||||
exprs.add({"4*5+5"_s, 4*5+5});
|
exprs.add({"4*5+5"_s, 4*5+5});
|
||||||
exprs.add({"4+5+5+3"_s, 4+5+5+3});
|
exprs.add({"4+5+5+3"_s, 4+5+5+3});
|
||||||
|
|
||||||
Iter(exprs){
|
For(exprs){
|
||||||
lex_restream(&ctx, it->str, "test_expr"_s);
|
lex_restream(&ctx, it->str, "test_expr"_s);
|
||||||
Ast_Expr *result = parse_expr();
|
Ast_Expr *result = parse_expr();
|
||||||
S64 val = expr_eval(result);
|
S64 val = expr_eval(result);
|
||||||
@@ -341,12 +353,11 @@ test_parse_expr(){
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Parsing declarations
|
// Parsing declarations
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// [10]*int - Array of 10 pointers to ints
|
// [10]*int - Array of 10 pointers to ints
|
||||||
function Ast_Typespec *
|
function Ast_Typespec *
|
||||||
parse_typespec_recurse(){
|
parse_typespec_recurse(){
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
if(token_match(TK_BitXor)){
|
if(token_match(TK_Pointer)){
|
||||||
Ast_Typespec *result = parse_typespec_recurse();
|
Ast_Typespec *result = parse_typespec_recurse();
|
||||||
result = ast_typespec_pointer(token, result);
|
result = ast_typespec_pointer(token, result);
|
||||||
return result;
|
return result;
|
||||||
@@ -395,20 +406,20 @@ parse_decl(){
|
|||||||
Ast_Expr *expr = parse_expr();
|
Ast_Expr *expr = parse_expr();
|
||||||
result = ast_decl_const(name, name->intern_val, expr);
|
result = ast_decl_const(name, name->intern_val, expr);
|
||||||
}
|
}
|
||||||
else if(token_match(TK_Colon)){
|
else if(token_match(TK_Colon)){
|
||||||
Ast_Typespec *typespec = 0;
|
Ast_Typespec *typespec = 0;
|
||||||
Ast_Expr *expr = 0;
|
Ast_Expr *expr = 0;
|
||||||
if(!token_is(TK_Assign)) typespec = parse_typespec();
|
if(!token_is(TK_Assign)) typespec = parse_typespec();
|
||||||
if(token_match(TK_Assign)) expr = parse_expr();
|
if(token_match(TK_Assign)) expr = parse_expr();
|
||||||
if(!expr && !typespec) parsing_error(name, "invalid declaration, no type or value");
|
if(!expr && !typespec) parsing_error(name, "invalid declaration, no type or value");
|
||||||
|
|
||||||
result = ast_decl_var(name, typespec, name->intern_val, expr);
|
result = ast_decl_var(name, typespec, name->intern_val, expr);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str);
|
parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
215
new_resolve.cpp
215
new_resolve.cpp
@@ -1,4 +1,4 @@
|
|||||||
#define Ast_Begin(kind,type) case kind: { type *node = (type *)ast;
|
#define Ast_Begin(kind,type) case kind: { type *node = (type *)ast;
|
||||||
#define Ast_End() } break
|
#define Ast_End() } break
|
||||||
|
|
||||||
enum Sym_Kind{
|
enum Sym_Kind{
|
||||||
@@ -12,7 +12,7 @@ struct Sym{
|
|||||||
Intern_String name;
|
Intern_String name;
|
||||||
Sym_Kind kind;
|
Sym_Kind kind;
|
||||||
Ast_Decl *decl;
|
Ast_Decl *decl;
|
||||||
Type *type;
|
Ast_Resolved_Type *type;
|
||||||
union{
|
union{
|
||||||
S64 int_val;
|
S64 int_val;
|
||||||
Intern_String intern_val;
|
Intern_String intern_val;
|
||||||
@@ -20,7 +20,7 @@ struct Sym{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Operand{
|
struct Operand{
|
||||||
Type *type;
|
Ast_Resolved_Type *type;
|
||||||
bool is_const;
|
bool is_const;
|
||||||
union {
|
union {
|
||||||
S64 int_val;
|
S64 int_val;
|
||||||
@@ -33,9 +33,9 @@ sym_insert(Sym *sym){
|
|||||||
U64 hash = hash_string(sym->name.s);
|
U64 hash = hash_string(sym->name.s);
|
||||||
Sym *is_sym = (Sym *)map_get_u64(&pctx->global_syms, hash);
|
Sym *is_sym = (Sym *)map_get_u64(&pctx->global_syms, hash);
|
||||||
if(is_sym){
|
if(is_sym){
|
||||||
parsing_error(sym->decl->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str);
|
parsing_error(sym->decl->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str);
|
||||||
}
|
}
|
||||||
|
|
||||||
map_insert_u64(&pctx->global_syms, hash, sym);
|
map_insert_u64(&pctx->global_syms, hash, sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ sym_get(Intern_String name){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Sym *
|
function Sym *
|
||||||
sym_new(Sym_Kind kind, Intern_String name, Type *type, Ast_Decl *decl){
|
sym_new(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Ast_Decl *decl){
|
||||||
Sym *result = exp_alloc_type(pctx->perm, Sym);
|
Sym *result = exp_alloc_type(pctx->perm, Sym);
|
||||||
result->name = name;
|
result->name = name;
|
||||||
result->kind = kind;
|
result->kind = kind;
|
||||||
@@ -57,7 +57,7 @@ sym_new(Sym_Kind kind, Intern_String name, Type *type, Ast_Decl *decl){
|
|||||||
|
|
||||||
global Ast_Decl empty_decl = {};
|
global Ast_Decl empty_decl = {};
|
||||||
function void
|
function void
|
||||||
sym_insert_builtin_type(String name, Type *type){
|
sym_insert_builtin_type(String name, Ast_Resolved_Type *type){
|
||||||
Intern_String string = intern_string(&pctx->interns, name);
|
Intern_String string = intern_string(&pctx->interns, name);
|
||||||
Sym *sym = sym_new(SYM_Type, string, type, &empty_decl);
|
Sym *sym = sym_new(SYM_Type, string, type, &empty_decl);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
@@ -69,33 +69,31 @@ sym_insert_builtins(){
|
|||||||
sym_insert_builtin_type("bool"_s, type_bool);
|
sym_insert_builtin_type("bool"_s, type_bool);
|
||||||
sym_insert_builtin_type("int"_s, type_int);
|
sym_insert_builtin_type("int"_s, type_int);
|
||||||
sym_insert_builtin_type("String"_s, type_string);
|
sym_insert_builtin_type("String"_s, type_string);
|
||||||
|
|
||||||
{
|
{
|
||||||
Intern_String string = intern_string(&pctx->interns, "true"_s);
|
Intern_String string = intern_string(&pctx->interns, "true"_s);
|
||||||
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
|
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Intern_String string = intern_string(&pctx->interns, "false"_s);
|
Intern_String string = intern_string(&pctx->interns, "false"_s);
|
||||||
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
|
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Intern_String string = intern_string(&pctx->interns, "null"_s);
|
Intern_String string = intern_string(&pctx->interns, "null"_s);
|
||||||
Sym *sym = sym_new(SYM_Const, string, type_null, &empty_decl);
|
Sym *sym = sym_new(SYM_Const, string, type_null, &empty_decl);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Operand eval_expr(Ast_Expr *ast, Type *compound_required_type = 0);
|
function Operand eval_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0);
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
eval_typespec(Ast_Typespec *ast){
|
eval_typespec(Ast_Typespec *ast){
|
||||||
if(!ast) return 0;
|
if(!ast) return 0;
|
||||||
|
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
Ast_Begin(AST_TYPESPEC_IDENT, Ast_Typespec){
|
Ast_Begin(AST_TYPESPEC_IDENT, Ast_Typespec){
|
||||||
Sym *type_sym = sym_get(node->name);
|
Sym *type_sym = sym_get(node->name);
|
||||||
@@ -105,34 +103,36 @@ eval_typespec(Ast_Typespec *ast){
|
|||||||
if(type_sym->kind != SYM_Type){
|
if(type_sym->kind != SYM_Type){
|
||||||
parsing_error(node->pos, "This identifier is not a type");
|
parsing_error(node->pos, "This identifier is not a type");
|
||||||
}
|
}
|
||||||
return type_sym->type;
|
|
||||||
|
node->resolved_type = type_sym->type;
|
||||||
|
return node->resolved_type;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_TYPESPEC_LAMBDA, Ast_Typespec){
|
Ast_Begin(AST_TYPESPEC_LAMBDA, Ast_Typespec){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Type *ret = eval_typespec(node->lambda->ret);
|
Ast_Resolved_Type *ret = eval_typespec(node->lambda->ret);
|
||||||
Array<Type *> params = {scratch};
|
Array<Ast_Resolved_Type *> params = {scratch};
|
||||||
For(node->lambda->params) params.add(eval_typespec(it[0]->lambda_param.typespec));
|
For(node->lambda->params) params.add(eval_typespec(it[0]->lambda_param.typespec));
|
||||||
Type *result = type_lambda(ret, params);
|
node->resolved_type = type_lambda(ret, params);
|
||||||
return result;
|
return node->resolved_type;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_TYPESPEC_POINTER, Ast_Typespec){
|
Ast_Begin(AST_TYPESPEC_POINTER, Ast_Typespec){
|
||||||
Type *type = eval_typespec(node->base);
|
Ast_Resolved_Type *type = eval_typespec(node->base);
|
||||||
Type *result = type_pointer(type);
|
node->resolved_type = type_pointer(type);
|
||||||
return result;
|
return node->resolved_type;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_TYPESPEC_ARRAY, Ast_Typespec){
|
Ast_Begin(AST_TYPESPEC_ARRAY, Ast_Typespec){
|
||||||
Type *type = eval_typespec(node->arr.base);
|
Ast_Resolved_Type *type = eval_typespec(node->arr.base);
|
||||||
Operand expr = eval_expr(node->arr.expr);
|
Operand expr = eval_expr(node->arr.expr);
|
||||||
if(!expr.is_const) parsing_error(node->pos, "Array size is not a constant");
|
if(!expr.is_const) parsing_error(node->pos, "Array size is not a constant");
|
||||||
if(expr.type != type_int) parsing_error(node->pos, "Array size is expected to be of type int");
|
if(expr.type != type_int) parsing_error(node->pos, "Array size is expected to be of type [Int] is instead of type %s", type_names[expr.type->kind]);
|
||||||
Type *result = type_array(type, expr.int_val);
|
node->resolved_type = type_array(type, expr.int_val);
|
||||||
return result;
|
return node->resolved_type;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
@@ -140,43 +140,94 @@ eval_typespec(Ast_Typespec *ast){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
resolve_type_pair(Token *pos, Type *a, Type *b){
|
resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){
|
||||||
Type *result = 0;
|
Ast_Resolved_Type *result = 0;
|
||||||
if(!a && b) result = b;
|
if(!a && b) result = b;
|
||||||
else if(a && !b) result = a;
|
else if(a && !b) result = a;
|
||||||
else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are null");
|
else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are [Null]");
|
||||||
else{ // a && b
|
else{ // a && b
|
||||||
if(b->kind == TYPE_Null) result = a;
|
if(b->kind == TYPE_Null) result = a;
|
||||||
else if(a->kind == TYPE_Null) result = b;
|
else if(a->kind == TYPE_Null) result = b;
|
||||||
else if(a != b) parsing_error(pos, "Expression and type specification are differing");
|
else if(a != b) parsing_error(pos, "Expression and type specification are differing %s %s", type_names[a->kind], type_names[b->kind]);
|
||||||
else result = a; // Types are the same
|
else result = a; // Types are the same
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(result->kind == TYPE_Null) parsing_error(pos, "Couldn't infer type of null value");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
Ast_Begin(AST_INT, Ast_Expr){
|
Ast_Begin(AST_INT, Ast_Expr){
|
||||||
Operand result = {type_int, true, {.int_val=(S64)node->int_val}};
|
Operand result = {type_int, true, {.int_val=(S64)node->int_val}};
|
||||||
return result;
|
return result;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_STR, Ast_Expr){
|
Ast_Begin(AST_STR, Ast_Expr){
|
||||||
Operand result = {type_string, true, {.intern_val = node->intern_val}};
|
Operand result = {type_string, true, {.intern_val = node->intern_val}};
|
||||||
return result;
|
return result;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_IDENT, Ast_Expr){
|
||||||
|
Sym *sym = sym_get(node->intern_val);
|
||||||
|
if(!sym){
|
||||||
|
parsing_error(node->pos, "Identifier is undefined");
|
||||||
|
}
|
||||||
|
|
||||||
|
// @note: check if null and rewrite the expression to match the expected type
|
||||||
|
Operand result = {};
|
||||||
|
if(sym->type->kind == TYPE_Null){
|
||||||
|
if(!expected_type) parsing_error(node->pos, "Couldn't infer type of null");
|
||||||
|
result.type = expected_type;
|
||||||
|
result.is_const = true;
|
||||||
|
if(expected_type == type_int){
|
||||||
|
result.int_val = 0;
|
||||||
|
node->kind = AST_INT;
|
||||||
|
node->int_val = 0;
|
||||||
|
}
|
||||||
|
else if(expected_type->kind == TYPE_Pointer){
|
||||||
|
result.int_val = 0;
|
||||||
|
node->kind = AST_IDENT;
|
||||||
|
node->intern_val = pctx->intern("null_pointer"_s);
|
||||||
|
}
|
||||||
|
else if(expected_type->kind == TYPE_Lambda){
|
||||||
|
result.int_val = 0;
|
||||||
|
node->kind = AST_IDENT;
|
||||||
|
node->intern_val = pctx->intern("null_lambda"_s);
|
||||||
|
}
|
||||||
|
else if(expected_type == type_bool){
|
||||||
|
result.int_val = 0;
|
||||||
|
node->kind = AST_IDENT;
|
||||||
|
node->intern_val = pctx->intern("false"_s);
|
||||||
|
}
|
||||||
|
else if(expected_type == type_string){
|
||||||
|
result.intern_val = pctx->intern(""_s);
|
||||||
|
node->kind = AST_STR;
|
||||||
|
node->intern_val = result.intern_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result.type = sym->type;
|
||||||
|
result.is_const = sym->kind == SYM_Const ? true : false;
|
||||||
|
result.int_val = sym->int_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_LAMBDA, Ast_Lambda){
|
Ast_Begin(AST_LAMBDA, Ast_Lambda){
|
||||||
Type *type = eval_typespec(ast_typespec_lambda(0, node));
|
Ast_Resolved_Type *type = eval_typespec(ast_typespec_lambda(0, node));
|
||||||
return {type, true};
|
return {type, true};
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_INDEX, Ast_Expr){
|
Ast_Begin(AST_INDEX, Ast_Expr){
|
||||||
Operand left = eval_expr(node->index.expr);
|
Operand left = eval_expr(node->index.expr);
|
||||||
Operand index = eval_expr(node->index.index);
|
Operand index = eval_expr(node->index.index);
|
||||||
@@ -186,81 +237,71 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
|||||||
return result;
|
return result;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_COMPOUND, Ast_Expr){
|
Ast_Begin(AST_COMPOUND, Ast_Expr){
|
||||||
Type *type = eval_typespec(node->compound.typespec);
|
Ast_Resolved_Type *type = eval_typespec(node->compound.typespec);
|
||||||
Type *variable_type = exp_compound_type;
|
Ast_Resolved_Type *variable_type = expected_type;
|
||||||
if(!type && variable_type) type = variable_type;
|
if(!type && variable_type) type = variable_type;
|
||||||
else if(!variable_type && type);
|
else if(!variable_type && type);
|
||||||
else if(variable_type != type) parsing_error(node->pos, "Variable type different from explicit compound type");
|
else if(variable_type != type) parsing_error(node->pos, "Variable type different from explicit compound type");
|
||||||
|
node->compound.type = type;
|
||||||
|
|
||||||
if(type->kind == TYPE_Array){
|
if(type->kind == TYPE_Array){
|
||||||
if(node->compound.exprs.len > type->arr.size) parsing_error(node->pos, "compound statement has too many items for this type");
|
if(node->compound.exprs.len > type->arr.size) parsing_error(node->pos, "compound statement has too many items for this type");
|
||||||
Type *item_type = type->arr.base;
|
Ast_Resolved_Type *item_type = type->arr.base;
|
||||||
|
|
||||||
For(node->compound.exprs){
|
For(node->compound.exprs){
|
||||||
assert(it[0]->kind == AST_COMPOUND_ITEM);
|
assert(it[0]->kind == AST_COMPOUND_ITEM);
|
||||||
Ast_Expr *i = (Ast_Expr *)it[0];
|
Ast_Expr *i = (Ast_Expr *)it[0];
|
||||||
assert(i->kind == AST_COMPOUND_ITEM);
|
assert(i->kind == AST_COMPOUND_ITEM);
|
||||||
if(i->compound_item.name) parsing_error(i->pos, "Invalid array indexing in compound expression");
|
if(i->compound_item.name) parsing_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]);
|
||||||
if(i->compound_item.index){
|
if(i->compound_item.index){
|
||||||
Operand index_op = eval_expr(i->compound_item.index);
|
Operand index_op = eval_expr(i->compound_item.index);
|
||||||
if(!index_op.is_const) parsing_error(i->pos, "Index in a compound expression is not a constant");
|
if(!index_op.is_const) parsing_error(i->pos, "Index in a compound expression is not a constant");
|
||||||
if(index_op.type != type_int) parsing_error(i->pos, "Index should be of type int");
|
if(index_op.type != type_int) parsing_error(i->pos, "Index should be of type int");
|
||||||
if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
||||||
}
|
}
|
||||||
Operand expr = eval_expr(i->compound_item.item);
|
Operand expr = eval_expr(i->compound_item.item, item_type);
|
||||||
resolve_type_pair(i->pos, expr.type, item_type);
|
resolve_type_pair(i->pos, expr.type, item_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else parsing_error(node->pos, "Invalid compound expression type");
|
else parsing_error(node->pos, "Invalid compound expression type");
|
||||||
|
|
||||||
Operand result = {type, false};
|
Operand result = {type, false};
|
||||||
return result;
|
return result;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_IDENT, Ast_Expr){
|
|
||||||
Sym *sym = sym_get(node->intern_val);
|
|
||||||
if(!sym){
|
|
||||||
parsing_error(node->pos, "Identifier is undefined");
|
|
||||||
}
|
|
||||||
|
|
||||||
Operand result = {sym->type, sym->kind == SYM_Const ? true : false, {.int_val = sym->int_val}};
|
|
||||||
return result;
|
|
||||||
Ast_End();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ast_Begin(AST_CAST, Ast_Expr){
|
Ast_Begin(AST_CAST, Ast_Expr){
|
||||||
Operand expr = eval_expr(node->cast.expr);
|
Operand expr = eval_expr(node->cast.expr);
|
||||||
Type *type = eval_typespec(node->cast.typespec);
|
Ast_Resolved_Type *type = eval_typespec(node->cast.typespec);
|
||||||
|
|
||||||
if(type == expr.type) return expr;
|
if(type == expr.type) return expr;
|
||||||
|
|
||||||
else if(expr.type == type_int && type == type_bool){
|
else if(expr.type == type_int && type == type_bool){
|
||||||
expr.type = type_bool;
|
expr.type = type_bool;
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(expr.type == type_bool && type == type_int){
|
else if(expr.type == type_bool && type == type_int){
|
||||||
expr.type = type_int;
|
expr.type = type_int;
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(expr.type == type_null){
|
else if(expr.type == type_null){
|
||||||
expr.type = type;
|
expr.type = type;
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
else parsing_error(node->pos, "Failed to cast, incompatible types");
|
else parsing_error(node->pos, "Failed to cast, incompatible types");
|
||||||
|
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_UNARY, Ast_Expr){
|
Ast_Begin(AST_UNARY, Ast_Expr){
|
||||||
Operand value = eval_expr(node->unary.expr);
|
Operand value = eval_expr(node->unary.expr);
|
||||||
switch(node->unary.op){
|
switch(node->unary.op){
|
||||||
case TK_BitXor:{
|
case TK_Pointer:{
|
||||||
if(value.type->kind != TYPE_Pointer) parsing_error(node->pos, "Dereferencing a value that is not a pointer");
|
if(value.type->kind != TYPE_Pointer) parsing_error(node->pos, "Dereferencing a value that is not a pointer");
|
||||||
Operand result = {value.type->base};
|
Operand result = {value.type->base};
|
||||||
return result;
|
return result;
|
||||||
@@ -271,10 +312,10 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
|||||||
}break;
|
}break;
|
||||||
invalid_default_case; return {};
|
invalid_default_case; return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_BINARY, Ast_Expr){
|
Ast_Begin(AST_BINARY, Ast_Expr){
|
||||||
Operand left = eval_expr(ast->binary.left);
|
Operand left = eval_expr(ast->binary.left);
|
||||||
Operand right = eval_expr(ast->binary.right);
|
Operand right = eval_expr(ast->binary.right);
|
||||||
@@ -293,51 +334,51 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
|||||||
}
|
}
|
||||||
else parsing_error(node->pos, "Arithmetic on type [TODO] is not supported");
|
else parsing_error(node->pos, "Arithmetic on type [TODO] is not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
eval_decl(Ast *ast){
|
eval_decl(Ast *ast){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
|
|
||||||
Ast_Begin(AST_PACKAGE, Ast_Package){
|
Ast_Begin(AST_PACKAGE, Ast_Package){
|
||||||
For(node->decls) eval_decl(*it);
|
For(node->decls) eval_decl(*it);
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_VAR, Ast_Decl){
|
Ast_Begin(AST_VAR, Ast_Decl){
|
||||||
Type *type = eval_typespec(node->var.typespec);
|
Ast_Resolved_Type *type = eval_typespec(node->var.typespec);
|
||||||
Operand expr = node->var.expr ? eval_expr(node->var.expr, type) : Operand{};
|
Operand expr = node->var.expr ? eval_expr(node->var.expr, type) : Operand{};
|
||||||
Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
|
Ast_Resolved_Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
|
||||||
|
|
||||||
Sym *sym = sym_new(SYM_Var, node->name, resolved_type, node);
|
Sym *sym = sym_new(SYM_Var, node->name, resolved_type, node);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_CONST, Ast_Decl){
|
Ast_Begin(AST_CONST, Ast_Decl){
|
||||||
Type *type = eval_typespec(node->var.typespec);
|
Ast_Resolved_Type *type = eval_typespec(node->var.typespec);
|
||||||
if(type && type->kind == TYPE_Pointer) parsing_error(node->pos, "Const cant be a pointer");
|
if(type && type->kind == TYPE_Pointer) parsing_error(node->pos, "Const cant be a pointer");
|
||||||
Operand expr = eval_expr(node->var.expr);
|
Operand expr = eval_expr(node->var.expr);
|
||||||
if(!expr.type) parsing_error(node->pos, "Constant value without expression");
|
if(!expr.type) parsing_error(node->pos, "Constant value without expression");
|
||||||
if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression");
|
if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression");
|
||||||
Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
|
Ast_Resolved_Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
|
||||||
|
|
||||||
Sym *sym = sym_new(SYM_Const, node->name, resolved_type, node);
|
Sym *sym = sym_new(SYM_Const, node->name, resolved_type, node);
|
||||||
if(resolved_type == type_int) sym->int_val = expr.int_val;
|
if(resolved_type == type_int) sym->int_val = expr.int_val;
|
||||||
else if(resolved_type == type_string) sym->intern_val = expr.intern_val;
|
else if(resolved_type == type_string) sym->intern_val = expr.intern_val;
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
142
new_type.cpp
142
new_type.cpp
@@ -1,4 +1,4 @@
|
|||||||
enum Type_Kind{
|
enum Ast_Resolved_Type_Kind{
|
||||||
TYPE_None,
|
TYPE_None,
|
||||||
TYPE_Null,
|
TYPE_Null,
|
||||||
TYPE_Int,
|
TYPE_Int,
|
||||||
@@ -8,41 +8,41 @@ enum Type_Kind{
|
|||||||
TYPE_Void,
|
TYPE_Void,
|
||||||
TYPE_Pointer,
|
TYPE_Pointer,
|
||||||
TYPE_Array,
|
TYPE_Array,
|
||||||
TYPE_Func,
|
TYPE_Lambda,
|
||||||
TYPE_Struct,
|
TYPE_Struct,
|
||||||
TYPE_Union,
|
TYPE_Union,
|
||||||
TYPE_Enum,
|
TYPE_Enum,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *type_names[] = {
|
const char *type_names[] = {
|
||||||
"[Invalid Type]",
|
"[Invalid Ast_Resolved_Type]",
|
||||||
"[TYPE_Null]",
|
"[Null]",
|
||||||
"[TYPE_Int]",
|
"[Int]",
|
||||||
"[TYPE_Bool]",
|
"[Bool]",
|
||||||
"[TYPE_Unsigned]",
|
"[Unsigned]",
|
||||||
"[TYPE_String]",
|
"[String]",
|
||||||
"[TYPE_Void]",
|
"[Void]",
|
||||||
"[TYPE_Pointer]",
|
"[Pointer]",
|
||||||
"[TYPE_Array]",
|
"[Array]",
|
||||||
"[TYPE_Func]",
|
"[Lambda]",
|
||||||
"[TYPE_Struct]",
|
"[Struct]",
|
||||||
"[TYPE_Union]",
|
"[Union]",
|
||||||
"[TYPE_Enum]",
|
"[Enum]",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Type{
|
struct Ast_Resolved_Type{
|
||||||
Type_Kind kind;
|
Ast_Resolved_Type_Kind kind;
|
||||||
SizeU size;
|
SizeU size;
|
||||||
SizeU align;
|
SizeU align;
|
||||||
union{
|
union{
|
||||||
Type *base;
|
Ast_Resolved_Type *base;
|
||||||
struct{
|
struct{
|
||||||
Type *base;
|
Ast_Resolved_Type *base;
|
||||||
SizeU size;
|
SizeU size;
|
||||||
}arr;
|
}arr;
|
||||||
struct{
|
struct{
|
||||||
Type *ret;
|
Ast_Resolved_Type *ret;
|
||||||
Array<Type*> args;
|
Array<Ast_Resolved_Type*> args;
|
||||||
}func;
|
}func;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -50,39 +50,39 @@ struct Type{
|
|||||||
const SizeU pointer_size = sizeof(SizeU);
|
const SizeU pointer_size = sizeof(SizeU);
|
||||||
const SizeU pointer_align = __alignof(SizeU);
|
const SizeU pointer_align = __alignof(SizeU);
|
||||||
|
|
||||||
global Type type__null = {TYPE_Null};
|
global Ast_Resolved_Type type__null = {TYPE_Null};
|
||||||
global Type type__void = {TYPE_Void};
|
global Ast_Resolved_Type type__void = {TYPE_Void};
|
||||||
global Type type__int = {TYPE_Int, sizeof(int), __alignof(int)};
|
global Ast_Resolved_Type type__int = {TYPE_Int, sizeof(int), __alignof(int)};
|
||||||
global Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)};
|
global Ast_Resolved_Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)};
|
||||||
global Type type__string = {TYPE_String, sizeof(String), __alignof(String)};
|
global Ast_Resolved_Type type__string = {TYPE_String, sizeof(String), __alignof(String)};
|
||||||
global Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)};
|
global Ast_Resolved_Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)};
|
||||||
|
|
||||||
global Type *type_void = &type__void;
|
global Ast_Resolved_Type *type_void = &type__void;
|
||||||
global Type *type_int = &type__int;
|
global Ast_Resolved_Type *type_int = &type__int;
|
||||||
global Type *type_unsigned = &type__unsigned;
|
global Ast_Resolved_Type *type_unsigned = &type__unsigned;
|
||||||
global Type *type_string = &type__string;
|
global Ast_Resolved_Type *type_string = &type__string;
|
||||||
global Type *type_bool = &type__bool;
|
global Ast_Resolved_Type *type_bool = &type__bool;
|
||||||
global Type *type_null = &type__null;
|
global Ast_Resolved_Type *type_null = &type__null;
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
type_new(Allocator *allocator, Type_Kind kind, SizeU size, SizeU align){
|
type_new(Allocator *allocator, Ast_Resolved_Type_Kind kind, SizeU size, SizeU align){
|
||||||
Type *result = exp_alloc_type(allocator, Type);
|
Ast_Resolved_Type *result = exp_alloc_type(allocator, Ast_Resolved_Type);
|
||||||
result->kind = kind;
|
result->kind = kind;
|
||||||
result->size = size;
|
result->size = size;
|
||||||
result->align = align;
|
result->align = align;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
type_copy(Allocator *a, Type *type){
|
type_copy(Allocator *a, Ast_Resolved_Type *type){
|
||||||
Type *result = exp_alloc_type(a, Type);
|
Ast_Resolved_Type *result = exp_alloc_type(a, Ast_Resolved_Type);
|
||||||
memory_copy(result, type, sizeof(Type));
|
memory_copy(result, type, sizeof(Ast_Resolved_Type));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
type_pointer(Type *base){
|
type_pointer(Ast_Resolved_Type *base){
|
||||||
Type *result = (Type *)map_get(&pctx->type_map, (void *)base);
|
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, (void *)base);
|
||||||
if(!result){
|
if(!result){
|
||||||
result = type_new(pctx->perm, TYPE_Pointer, pointer_size, pointer_align);
|
result = type_new(pctx->perm, TYPE_Pointer, pointer_size, pointer_align);
|
||||||
result->base = base;
|
result->base = base;
|
||||||
@@ -92,17 +92,17 @@ type_pointer(Type *base){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
type_array(Type *base, SizeU size){
|
type_array(Ast_Resolved_Type *base, SizeU size){
|
||||||
U64 hash = hash_mix(hash_ptr(base), hash_u64(size));
|
U64 hash = hash_mix(hash_ptr(base), hash_u64(size));
|
||||||
Type *result = (Type *)map_get_u64(&pctx->type_map, hash);
|
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get_u64(&pctx->type_map, hash);
|
||||||
if(result){
|
if(result){
|
||||||
assert(result->kind == TYPE_Array);
|
assert(result->kind == TYPE_Array);
|
||||||
assert(result->arr.size == size);
|
assert(result->arr.size == size);
|
||||||
assert(result->arr.base == base);
|
assert(result->arr.base == base);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = type_new(pctx->perm, TYPE_Array, pointer_size, pointer_align);
|
result = type_new(pctx->perm, TYPE_Array, pointer_size, pointer_align);
|
||||||
result->arr.base = base;
|
result->arr.base = base;
|
||||||
result->arr.size = size;
|
result->arr.size = size;
|
||||||
@@ -110,24 +110,24 @@ type_array(Type *base, SizeU size){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
type_lambda(Type *ret, Array<Type *> args){
|
type_lambda(Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
|
||||||
U64 hash = hash_ptr(ret);
|
U64 hash = hash_ptr(ret);
|
||||||
For(args) hash = hash_mix(hash, hash_ptr(*it));
|
For(args) hash = hash_mix(hash, hash_ptr(*it));
|
||||||
Type *result = (Type *)map_get_u64(&pctx->type_map, hash);
|
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get_u64(&pctx->type_map, hash);
|
||||||
|
|
||||||
if(result){
|
if(result){
|
||||||
assert(result->kind == TYPE_Func);
|
assert(result->kind == TYPE_Lambda);
|
||||||
assert(result->func.ret == ret);
|
assert(result->func.ret == ret);
|
||||||
assert(result->func.args.len == args.len);
|
assert(result->func.args.len == args.len);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = type_new(pctx->perm, TYPE_Func, pointer_size, pointer_align);
|
result = type_new(pctx->perm, TYPE_Lambda, pointer_size, pointer_align);
|
||||||
result->func.ret = ret;
|
result->func.ret = ret;
|
||||||
result->func.args = args.tight_copy(pctx->perm);
|
result->func.args = args.tight_copy(pctx->perm);
|
||||||
map_insert_u64(&pctx->type_map, hash, result);
|
map_insert_u64(&pctx->type_map, hash, result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,34 +137,34 @@ test_types(){
|
|||||||
Parse_Ctx ctx = {};
|
Parse_Ctx ctx = {};
|
||||||
ctx.init(scratch, scratch);
|
ctx.init(scratch, scratch);
|
||||||
pctx = &ctx;
|
pctx = &ctx;
|
||||||
|
|
||||||
Type *array_type1 = type_array(type_int, 32);
|
Ast_Resolved_Type *array_type1 = type_array(type_int, 32);
|
||||||
Type *array_type2 = type_array(type_int, 32);
|
Ast_Resolved_Type *array_type2 = type_array(type_int, 32);
|
||||||
Type *array_type3 = type_array(type_int, 48);
|
Ast_Resolved_Type *array_type3 = type_array(type_int, 48);
|
||||||
assert(array_type1 == array_type2);
|
assert(array_type1 == array_type2);
|
||||||
assert(array_type2 != array_type3);
|
assert(array_type2 != array_type3);
|
||||||
Type *pointer_type1 = type_pointer(type_int);
|
Ast_Resolved_Type *pointer_type1 = type_pointer(type_int);
|
||||||
Type *pointer_type2 = type_pointer(type_int);
|
Ast_Resolved_Type *pointer_type2 = type_pointer(type_int);
|
||||||
assert(pointer_type2 == pointer_type1);
|
assert(pointer_type2 == pointer_type1);
|
||||||
Type *pointer_type3 = type_pointer(pointer_type1);
|
Ast_Resolved_Type *pointer_type3 = type_pointer(pointer_type1);
|
||||||
Type *pointer_type4 = type_pointer(pointer_type2);
|
Ast_Resolved_Type *pointer_type4 = type_pointer(pointer_type2);
|
||||||
assert(pointer_type3 != pointer_type1);
|
assert(pointer_type3 != pointer_type1);
|
||||||
assert(pointer_type3 == pointer_type4);
|
assert(pointer_type3 == pointer_type4);
|
||||||
|
|
||||||
Array<Type*> types = {scratch};
|
Array<Ast_Resolved_Type*> types = {scratch};
|
||||||
types.add(type_array(type_int, 32));
|
types.add(type_array(type_int, 32));
|
||||||
Type *func_type1 = type_lambda(types[0], types);
|
Ast_Resolved_Type *func_type1 = type_lambda(types[0], types);
|
||||||
Type *func_type2 = type_lambda(types[0], types);
|
Ast_Resolved_Type *func_type2 = type_lambda(types[0], types);
|
||||||
assert(func_type1 == func_type2);
|
assert(func_type1 == func_type2);
|
||||||
|
|
||||||
Array<Type*> types2 = {scratch};
|
Array<Ast_Resolved_Type*> types2 = {scratch};
|
||||||
{
|
{
|
||||||
types2.add(type_array(type_int, 32));
|
types2.add(type_array(type_int, 32));
|
||||||
types2.add(type_int);
|
types2.add(type_int);
|
||||||
}
|
}
|
||||||
types.add(type_int);
|
types.add(type_int);
|
||||||
Type *func_type3 = type_lambda(types[0], types);
|
Ast_Resolved_Type *func_type3 = type_lambda(types[0], types);
|
||||||
Type *func_type4 = type_lambda(types[0], types2);
|
Ast_Resolved_Type *func_type4 = type_lambda(types[0], types2);
|
||||||
assert(func_type1 != func_type3);
|
assert(func_type1 != func_type3);
|
||||||
assert(func_type3 == func_type4);
|
assert(func_type3 == func_type4);
|
||||||
}
|
}
|
||||||
|
|||||||
294
output.cc
294
output.cc
@@ -1,294 +0,0 @@
|
|||||||
(((534>43)?435:42),234,((S64)32),Thing[10][2],Thing((1,2)))
|
|
||||||
(4+(2*53))
|
|
||||||
((4+2)*53)
|
|
||||||
(++5)
|
|
||||||
(--5)
|
|
||||||
(-5)
|
|
||||||
(+5)
|
|
||||||
(sizeof(32)+sizeof(S32*))
|
|
||||||
((S64**)5)
|
|
||||||
(((S64)5)+3)
|
|
||||||
((534>43)?435:42)
|
|
||||||
struct Thing{
|
|
||||||
int test;
|
|
||||||
};
|
|
||||||
|
|
||||||
S32 thing = 100;
|
|
||||||
(thing=(thing+10));
|
|
||||||
(++thing);
|
|
||||||
{
|
|
||||||
S32 thing_scoped = 10;
|
|
||||||
(thing_scoped+=10);
|
|
||||||
}
|
|
||||||
typedef struct OpenGL OpenGL;
|
|
||||||
typedef struct OS_Memory OS_Memory;
|
|
||||||
typedef struct Arena Arena;
|
|
||||||
typedef struct String String;
|
|
||||||
typedef struct Token Token;
|
|
||||||
typedef struct Lex_Stream Lex_Stream;
|
|
||||||
typedef struct Expr Expr;
|
|
||||||
typedef struct AST_Node AST_Node;
|
|
||||||
typedef struct Parser_Error Parser_Error;
|
|
||||||
typedef struct Scope Scope;
|
|
||||||
typedef struct Parser Parser;
|
|
||||||
struct test{
|
|
||||||
struct Array_Block{
|
|
||||||
Array_Block (*next);
|
|
||||||
Based_Type_Represent (data[size]);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Array{
|
|
||||||
Array_Block first;
|
|
||||||
Array_Block (*last);
|
|
||||||
S64 block;
|
|
||||||
S64 len;
|
|
||||||
};
|
|
||||||
|
|
||||||
function Based_Type_Represent array_make(Arena (*arena)){
|
|
||||||
Test_Type thing;
|
|
||||||
Based_Type_Represent result;
|
|
||||||
((result.arena)=arena);
|
|
||||||
((result.last)=(&(result.first)));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
function void array_push(Array (*array), Based_Type_Represent (*item)){
|
|
||||||
if (((array->len)+1)>size){
|
|
||||||
assert((array->len));
|
|
||||||
Array_Block (*block) = ((Thing)arena_push_struct(((array->arena),sizeof(Array_Block))));
|
|
||||||
((array->last)=(((array->last).next)=block));
|
|
||||||
((array->len)=0);
|
|
||||||
((array->block)+=1);
|
|
||||||
}
|
|
||||||
(((array->last).data)[(++(array->len))]=(*item));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OpenGL{
|
|
||||||
void (*glVertexAttribPointer)(GLuint, GLint, GLenumGLenum, GLboolean, GLsizei, GLvoid *);
|
|
||||||
void (*glBindTexture)(GLenum, GLuint);
|
|
||||||
void (*glDrawArrays)(GLenumGLenum, GLint, GLsizei);
|
|
||||||
int (*(test_array[10]));
|
|
||||||
Things (*thing);
|
|
||||||
S64 thing_cap;
|
|
||||||
S64 thing_len;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OS_Memory{
|
|
||||||
void (*data);
|
|
||||||
SizeU commit;
|
|
||||||
SizeU reserve;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Arena{
|
|
||||||
OS_Memory memory;
|
|
||||||
U64 len;
|
|
||||||
U64 alignment;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct String{
|
|
||||||
U8 (*str);
|
|
||||||
S64 len;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef String Intern_String;
|
|
||||||
typedef enum Token_Kind{
|
|
||||||
TK_End,
|
|
||||||
TK_Mul,
|
|
||||||
TK_Div,
|
|
||||||
TK_Add,
|
|
||||||
TK_Sub,
|
|
||||||
TK_Mod,
|
|
||||||
TK_BitAnd,
|
|
||||||
TK_BitOr,
|
|
||||||
TK_BitXor,
|
|
||||||
TK_Neg,
|
|
||||||
TK_Not,
|
|
||||||
TK_OpenParen,
|
|
||||||
TK_CloseParen,
|
|
||||||
TK_OpenBrace,
|
|
||||||
TK_CloseBrace,
|
|
||||||
TK_OpenBracket,
|
|
||||||
TK_CloseBracket,
|
|
||||||
TK_Comma,
|
|
||||||
TK_Pound,
|
|
||||||
TK_Question,
|
|
||||||
TK_ThreeDots,
|
|
||||||
TK_Semicolon,
|
|
||||||
TK_Dot,
|
|
||||||
TK_LesserThen,
|
|
||||||
TK_GreaterThen,
|
|
||||||
TK_Colon,
|
|
||||||
TK_Assign,
|
|
||||||
TK_DivAssign,
|
|
||||||
TK_MulAssign,
|
|
||||||
TK_ModAssign,
|
|
||||||
TK_SubAssign,
|
|
||||||
TK_AddAssign,
|
|
||||||
TK_AndAssign,
|
|
||||||
TK_OrAssign,
|
|
||||||
TK_XorAssign,
|
|
||||||
TK_LeftShiftAssign,
|
|
||||||
TK_RightShiftAssign,
|
|
||||||
TK_DoubleColon,
|
|
||||||
TK_At,
|
|
||||||
TK_Decrement,
|
|
||||||
TK_Increment,
|
|
||||||
TK_PostDecrement,
|
|
||||||
TK_PostIncrement,
|
|
||||||
TK_LesserThenOrEqual,
|
|
||||||
TK_GreaterThenOrEqual,
|
|
||||||
TK_Equals,
|
|
||||||
TK_And,
|
|
||||||
TK_Or,
|
|
||||||
TK_NotEquals,
|
|
||||||
TK_LeftShift,
|
|
||||||
TK_RightShift,
|
|
||||||
TK_Arrow,
|
|
||||||
TK_ExprSizeof,
|
|
||||||
TK_DocComment,
|
|
||||||
TK_Comment,
|
|
||||||
TK_Identifier,
|
|
||||||
TK_StringLit,
|
|
||||||
TK_U8Lit,
|
|
||||||
TK_Character,
|
|
||||||
TK_Error,
|
|
||||||
TK_Float,
|
|
||||||
TK_Int,
|
|
||||||
TK_Keyword,
|
|
||||||
}Token_Kind;
|
|
||||||
|
|
||||||
struct Token{
|
|
||||||
Token_Kind kind;
|
|
||||||
String string;
|
|
||||||
union{
|
|
||||||
S64 integer_val;
|
|
||||||
String error_val;
|
|
||||||
Intern_String intern_val;
|
|
||||||
};
|
|
||||||
String file;
|
|
||||||
S64 line;
|
|
||||||
U8 (*line_begin);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Lex_Stream{
|
|
||||||
U8 (*stream);
|
|
||||||
U8 (*line_begin);
|
|
||||||
String filename;
|
|
||||||
S64 line;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum Expr_Kind{
|
|
||||||
EK_None,
|
|
||||||
EK_Atom,
|
|
||||||
EK_Unary,
|
|
||||||
EK_Binary,
|
|
||||||
EK_Ternary,
|
|
||||||
EK_Cast,
|
|
||||||
EK_List,
|
|
||||||
EK_Call,
|
|
||||||
EK_Index,
|
|
||||||
}Expr_Kind;
|
|
||||||
|
|
||||||
struct Expr{
|
|
||||||
Expr_Kind kind;
|
|
||||||
Token (*token);
|
|
||||||
Expr (*next);
|
|
||||||
union{
|
|
||||||
struct{
|
|
||||||
AST_Node (*type);
|
|
||||||
Expr (*expr);
|
|
||||||
}cast_val;
|
|
||||||
struct{
|
|
||||||
Expr (*first);
|
|
||||||
Expr (*last);
|
|
||||||
}list;
|
|
||||||
struct{
|
|
||||||
Expr (*atom);
|
|
||||||
Expr (*list);
|
|
||||||
}call;
|
|
||||||
struct{
|
|
||||||
Expr (*atom);
|
|
||||||
Expr (*index);
|
|
||||||
}index;
|
|
||||||
struct{
|
|
||||||
Expr (*expr);
|
|
||||||
}unary;
|
|
||||||
struct{
|
|
||||||
Expr (*left);
|
|
||||||
Expr (*right);
|
|
||||||
}binary;
|
|
||||||
struct{
|
|
||||||
Expr (*cond);
|
|
||||||
Expr (*on_true);
|
|
||||||
Expr (*on_false);
|
|
||||||
}ternary;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum AST_Kind{
|
|
||||||
AK_None,
|
|
||||||
AK_BaseType,
|
|
||||||
AK_Typedef,
|
|
||||||
AK_Enum,
|
|
||||||
AK_Struct,
|
|
||||||
AK_Union,
|
|
||||||
AK_Note,
|
|
||||||
AK_List,
|
|
||||||
AK_Pointer,
|
|
||||||
AK_Array,
|
|
||||||
AK_Function,
|
|
||||||
AK_Variable,
|
|
||||||
AK_EnumChild,
|
|
||||||
}AST_Kind;
|
|
||||||
|
|
||||||
struct AST_Node{
|
|
||||||
AST_Kind kind;
|
|
||||||
Token (*pos);
|
|
||||||
Intern_String name;
|
|
||||||
AST_Node (*next);
|
|
||||||
AST_Node (*next_scope);
|
|
||||||
AST_Node (*first_note);
|
|
||||||
AST_Node (*last_note);
|
|
||||||
AST_Node (*first_child);
|
|
||||||
AST_Node (*last_child);
|
|
||||||
union{
|
|
||||||
SizeU base_type_size;
|
|
||||||
AST_Node (*pointer);
|
|
||||||
AST_Node (*typedef_type);
|
|
||||||
AST_Node (*variable_type);
|
|
||||||
AST_Node (*func_return_type);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Parser_Error{
|
|
||||||
Parser_Error (*next);
|
|
||||||
String message;
|
|
||||||
Token (*token);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Scope{
|
|
||||||
Scope (*next);
|
|
||||||
AST_Node (*first);
|
|
||||||
AST_Node (*last);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Parser{
|
|
||||||
Arena main_arena;
|
|
||||||
Arena intern_table_arena;
|
|
||||||
Arena symbol_table_arena;
|
|
||||||
Scope (*scope_free_list);
|
|
||||||
Scope (*scope_stack);
|
|
||||||
Scope (*global_scope);
|
|
||||||
S64 symbols_inserted;
|
|
||||||
S64 symbols_count;
|
|
||||||
AST_Node (*symbols);
|
|
||||||
Intern_String (*interns);
|
|
||||||
S64 interns_in_bytes;
|
|
||||||
S64 interns_inserted;
|
|
||||||
S64 interns_count;
|
|
||||||
U8 (*first_keyword);
|
|
||||||
U8 (*last_keyword);
|
|
||||||
Parser_Error default;
|
|
||||||
Parser_Error error;
|
|
||||||
};
|
|
||||||
|
|
||||||
74
parse.c
74
parse.c
@@ -9,7 +9,7 @@ struct Parser_Error{
|
|||||||
typedef struct Parser{
|
typedef struct Parser{
|
||||||
Token_Array tokens;
|
Token_Array tokens;
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
Parser_Error *first_error;
|
Parser_Error *first_error;
|
||||||
Parser_Error *last_error;
|
Parser_Error *last_error;
|
||||||
}Parser;
|
}Parser;
|
||||||
@@ -38,36 +38,36 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
|
|||||||
va_copy(args2, args1);
|
va_copy(args2, args1);
|
||||||
string.len = vsnprintf(0, 0, str, args2);
|
string.len = vsnprintf(0, 0, str, args2);
|
||||||
va_end(args2);
|
va_end(args2);
|
||||||
|
|
||||||
string.str = arena_push_size(p->arena, string.len + 1);
|
string.str = arena_push_size(p->arena, string.len + 1);
|
||||||
vsnprintf((char*)string.str, string.len + 1, str, args1);
|
vsnprintf((char*)string.str, string.len + 1, str, args1);
|
||||||
va_end(args1);
|
va_end(args1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Note(Krzosa): Print nice error message
|
// @Note(Krzosa): Print nice error message
|
||||||
printf("\nError: %s", string.str);
|
printf("\nError: %s", string.str);
|
||||||
if(token){
|
if(token){
|
||||||
printf(" %s:%d\n", token->file.str, (S32)token->line);
|
printf(" %s:%d\n", token->file.str, (S32)token->line);
|
||||||
|
|
||||||
// @Note(Krzosa): Print error line
|
// @Note(Krzosa): Print error line
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
|
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
|
||||||
printf("%.*s\n", i, token->line_begin);
|
printf("%.*s\n", i, token->line_begin);
|
||||||
|
|
||||||
// @Note(Krzosa): Print error marker
|
// @Note(Krzosa): Print error marker
|
||||||
int token_i = token->str - token->line_begin;
|
int token_i = token->str - token->line_begin;
|
||||||
for(int i = 0; i < token_i-2; i++) printf(" ");
|
for(int i = 0; i < token_i-2; i++) printf(" ");
|
||||||
printf("^^^^^^\n");
|
printf("^^^^^^\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser_Error *error = arena_push_struct(p->arena, Parser_Error);
|
Parser_Error *error = arena_push_struct(p->arena, Parser_Error);
|
||||||
error->message = string;
|
error->message = string;
|
||||||
error->next = 0;
|
error->next = 0;
|
||||||
error->token = token;
|
error->token = token;
|
||||||
SLLQueuePush(p->first_error, p->last_error, error);
|
SLLQueuePush(p->first_error, p->last_error, error);
|
||||||
|
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,15 +162,15 @@ compare = == | != | >= | > | <= | <
|
|||||||
logical = [&|^] | && | ||
|
logical = [&|^] | && | ||
|
||||||
unary = [&*-!~+] | ++ | --
|
unary = [&*-!~+] | ++ | --
|
||||||
|
|
||||||
atom_expr = Int
|
atom_expr = Int
|
||||||
| Float
|
| Float
|
||||||
| String
|
| String
|
||||||
| Identifier
|
| Identifier
|
||||||
| 'cast' '(' typespec ',' expr ')'
|
| 'cast' '(' typespec ',' expr ')'
|
||||||
| 'size_type' '(' typespec ')'
|
| 'size_type' '(' typespec ')'
|
||||||
| 'size_expr' '(' expr ')'
|
| 'size_expr' '(' expr ')'
|
||||||
| '{' compound_expr '}'
|
| '{' compound_expr '}'
|
||||||
| '(' expr ')'
|
| '(' expr ')'
|
||||||
| '(' ':' typespec ')' '{' compound_expr '}'
|
| '(' ':' typespec ')' '{' compound_expr '}'
|
||||||
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
|
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
|
||||||
unary_expr = unary ? unary_expr : atom_expr
|
unary_expr = unary ? unary_expr : atom_expr
|
||||||
@@ -205,7 +205,7 @@ parse_expr_compound_field(Parser *p){
|
|||||||
parser_push_error(p, token, "Failed to parse compound literal, required identifier as left value");
|
parser_push_error(p, token, "Failed to parse compound literal, required identifier as left value");
|
||||||
}
|
}
|
||||||
result = expr_compound_named(p->arena, token, expr->intern_val, parse_expr(p));
|
result = expr_compound_named(p->arena, token, expr->intern_val, parse_expr(p));
|
||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
result = expr_compound_default(p->arena, token, expr);
|
result = expr_compound_default(p->arena, token, expr);
|
||||||
@@ -251,7 +251,7 @@ parse_expr_atom(Parser *p){
|
|||||||
else if(token_is(p, TK_OpenBrace)){
|
else if(token_is(p, TK_OpenBrace)){
|
||||||
result = parse_expr_compound(p, 0);
|
result = parse_expr_compound(p, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(token_match(p, TK_OpenParen)){
|
else if(token_match(p, TK_OpenParen)){
|
||||||
if(token_match(p, TK_Colon)){
|
if(token_match(p, TK_Colon)){
|
||||||
Typespec *typespec = parse_typespec(p);
|
Typespec *typespec = parse_typespec(p);
|
||||||
@@ -343,7 +343,7 @@ parse_expr_postfix(Parser *p){
|
|||||||
function B32
|
function B32
|
||||||
token_is_unary(Parser *p){
|
token_is_unary(Parser *p){
|
||||||
Token *token = token_get(p);
|
Token *token = token_get(p);
|
||||||
B32 result = token->kind == TK_Add
|
B32 result = token->kind == TK_Add
|
||||||
|| token->kind == TK_Increment
|
|| token->kind == TK_Increment
|
||||||
|| token->kind == TK_Decrement
|
|| token->kind == TK_Decrement
|
||||||
|| token->kind == TK_Sub
|
|| token->kind == TK_Sub
|
||||||
@@ -462,15 +462,15 @@ parse_expr(Parser *p){
|
|||||||
// Type specifier parsing
|
// Type specifier parsing
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/*
|
/*
|
||||||
base_type = NAME
|
base_type = NAME
|
||||||
| '(' type_list? ')' type?
|
| '(' type_list? ')' type?
|
||||||
|
|
||||||
type = ('*' | '[' expr ']')* base_type
|
type = ('*' | '[' expr ']')* base_type
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
[32]*U32 - Array of 32 pointers to U32
|
[32]*U32 - Array of 32 pointers to U32
|
||||||
**CustomDataType - Pointer to pointer of CustomDataType
|
**CustomDataType - Pointer to pointer of CustomDataType
|
||||||
(*U32, S64) **S64 - Function pointer
|
(*U32, S64) **S64 - Function pointer
|
||||||
(CoolType: optional, S32) - Implicit void return value
|
(CoolType: optional, S32) - Implicit void return value
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@@ -490,9 +490,9 @@ parse_optional_type(Parser *p, Intern_String type){
|
|||||||
function Typespec *
|
function Typespec *
|
||||||
parse_typespec_function(Parser *p, Token *token){
|
parse_typespec_function(Parser *p, Token *token){
|
||||||
Typespec *result = typespec_function(p->arena, token, 0);
|
Typespec *result = typespec_function(p->arena, token, 0);
|
||||||
if(!token_is(p, TK_CloseParen))
|
if(!token_is(p, TK_CloseParen))
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
|
||||||
// Optional name
|
// Optional name
|
||||||
Token *name = 0;
|
Token *name = 0;
|
||||||
if((token = token_is(p, TK_Identifier))){
|
if((token = token_is(p, TK_Identifier))){
|
||||||
@@ -502,21 +502,21 @@ parse_typespec_function(Parser *p, Token *token){
|
|||||||
name = token;
|
name = token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse type
|
// Parse type
|
||||||
Typespec *arg = parse_typespec(p);
|
Typespec *arg = parse_typespec(p);
|
||||||
if(name)
|
if(name)
|
||||||
arg = typespec_named_argument(p->arena, name, arg, name->intern_val);
|
arg = typespec_named_argument(p->arena, name, arg, name->intern_val);
|
||||||
typespec_function_push(result, arg);
|
typespec_function_push(result, arg);
|
||||||
|
|
||||||
if(!token_match(p, TK_Comma)){
|
if(!token_match(p, TK_Comma)){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token_expect(p, TK_CloseParen);
|
token_expect(p, TK_CloseParen);
|
||||||
|
|
||||||
result->func.ret = parse_optional_type(p, intern_void);
|
result->func.ret = parse_optional_type(p, intern_void);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,7 +578,7 @@ name::const = 4254;
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
*/
|
*/
|
||||||
function void
|
function void
|
||||||
parse_note_list(Parser *p, AST_Parent *parent) {
|
parse_note_list(Parser *p, AST_Parent *parent) {
|
||||||
if(token_match(p, TK_OpenParen)) {
|
if(token_match(p, TK_OpenParen)) {
|
||||||
if(token_match(p, TK_CloseParen)){
|
if(token_match(p, TK_CloseParen)){
|
||||||
@@ -596,7 +596,7 @@ parse_note_list(Parser *p, AST_Parent *parent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
parse__notes(Parser *p, AST_Parent *result) {
|
parse__notes(Parser *p, AST_Parent *result) {
|
||||||
while(token_match(p, TK_At)) {
|
while(token_match(p, TK_At)) {
|
||||||
Token *name = token_expect(p, TK_Identifier);
|
Token *name = token_expect(p, TK_Identifier);
|
||||||
@@ -791,7 +791,7 @@ parse_decl(Parser *p, AST_Parent *parent){
|
|||||||
"token '%s'", token_kind_string[token->kind]);
|
"token '%s'", token_kind_string[token->kind]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result){
|
if(result){
|
||||||
result->notes = note;
|
result->notes = note;
|
||||||
ast_push_last(parent, result);
|
ast_push_last(parent, result);
|
||||||
@@ -806,7 +806,7 @@ parse_decl(Parser *p, AST_Parent *parent){
|
|||||||
function AST *parse_stmt(Parser *p);
|
function AST *parse_stmt(Parser *p);
|
||||||
/*
|
/*
|
||||||
stmt_list = '{' stmt* '}'
|
stmt_list = '{' stmt* '}'
|
||||||
stmt =
|
stmt =
|
||||||
| stmt_list
|
| stmt_list
|
||||||
| 'return' expr ';'
|
| 'return' expr ';'
|
||||||
| 'if' expr stmt_list
|
| 'if' expr stmt_list
|
||||||
@@ -969,11 +969,11 @@ parse_stmt(Parser *p){
|
|||||||
result = parse_simple_stmt(p);
|
result = parse_simple_stmt(p);
|
||||||
token_expect(p, TK_Semicolon);
|
token_expect(p, TK_Semicolon);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result){
|
if(result){
|
||||||
result->notes = notes;
|
result->notes = notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1017,7 +1017,7 @@ eval_expr(Expr *expr){
|
|||||||
case TK_LesserThen: return left < right; break;
|
case TK_LesserThen: return left < right; break;
|
||||||
case TK_BitAnd: return left & right; break;
|
case TK_BitAnd: return left & right; break;
|
||||||
case TK_BitOr: return left | right; break;
|
case TK_BitOr: return left | right; break;
|
||||||
case TK_BitXor: return left ^ right; break;
|
case TK_Pointer: return left ^ right; break;
|
||||||
case TK_And: return left && right; break;
|
case TK_And: return left && right; break;
|
||||||
case TK_Or: return left || right; break;
|
case TK_Or: return left || right; break;
|
||||||
case TK_LeftShift: return left << right; break;
|
case TK_LeftShift: return left << right; break;
|
||||||
@@ -1083,11 +1083,11 @@ parse_test_expr(){
|
|||||||
" 1>5 ? 1 : 2 "
|
" 1>5 ? 1 : 2 "
|
||||||
" !!!!!1 "
|
" !!!!!1 "
|
||||||
" ~~1 + -!2 "
|
" ~~1 + -!2 "
|
||||||
" 1 + ++Thing[12]++ + ++Thing[12].expr +"
|
" 1 + ++Thing[12]++ + ++Thing[12].expr +"
|
||||||
);
|
);
|
||||||
Parser parser = parser_make_stream(scratch, test_case, lit("Big_Expr"));
|
Parser parser = parser_make_stream(scratch, test_case, lit("Big_Expr"));
|
||||||
Parser *p = &parser;
|
Parser *p = &parser;
|
||||||
|
|
||||||
S64 t = 5;
|
S64 t = 5;
|
||||||
S64 test_val[] = {
|
S64 test_val[] = {
|
||||||
(32+52-242*2/424%5-23),
|
(32+52-242*2/424%5-23),
|
||||||
@@ -1106,7 +1106,7 @@ parse_test_expr(){
|
|||||||
S64 val = eval_expr(expr);
|
S64 val = eval_expr(expr);
|
||||||
assert(val == test_val[i]);
|
assert(val == test_val[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
String exprs[] = {
|
String exprs[] = {
|
||||||
lit("cast([12](thing: U32, qwe: *U32): [32]Result, (123+234))"),
|
lit("cast([12](thing: U32, qwe: *U32): [32]Result, (123+234))"),
|
||||||
lit("cast((thing: U32, qwe: *U32), (123+234))"),
|
lit("cast((thing: U32, qwe: *U32), (123+234))"),
|
||||||
@@ -1123,7 +1123,7 @@ parse_test_expr(){
|
|||||||
expr_print(expr);
|
expr_print(expr);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
arena_end_scratch();
|
arena_end_scratch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1131,7 +1131,7 @@ function void
|
|||||||
parse_test_decls(){
|
parse_test_decls(){
|
||||||
Arena *scratch = arena_begin_scratch();
|
Arena *scratch = arena_begin_scratch();
|
||||||
Parser p = parser_make(scratch);
|
Parser p = parser_make(scratch);
|
||||||
|
|
||||||
String decls[] = {
|
String decls[] = {
|
||||||
lit("Thing::enum: U64{ Thing_1 = 1<<1, Thing_2 = 2 }"),
|
lit("Thing::enum: U64{ Thing_1 = 1<<1, Thing_2 = 2 }"),
|
||||||
lit("Struct::struct{ thing, thing2: *S64; struct { thing:U32; thing2: [64]Vec2; } inner: struct {i:U32;} }"),
|
lit("Struct::struct{ thing, thing2: *S64; struct { thing:U32; thing2: [64]Vec2; } inner: struct {i:U32;} }"),
|
||||||
@@ -1156,7 +1156,7 @@ parse_test_from_file(){
|
|||||||
arena_end_scratch();
|
arena_end_scratch();
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
parse_test_stmt(){
|
parse_test_stmt(){
|
||||||
Arena *scratch = arena_begin_scratch();
|
Arena *scratch = arena_begin_scratch();
|
||||||
Parser p = parser_make(scratch);
|
Parser p = parser_make(scratch);
|
||||||
|
|||||||
286
test.cc
286
test.cc
@@ -1,286 +0,0 @@
|
|||||||
Thing :: const: *U32 = 0;
|
|
||||||
CONST_VAL::const = 185210591;
|
|
||||||
new_function::(Thing:[32]U32): U32;
|
|
||||||
|
|
||||||
@test(size = 4096)
|
|
||||||
OpenGL :: struct{
|
|
||||||
glVertexAttribPointer: (GLuint, GLint, GLenum, GLboolean, GLsizei, *GLvoid);
|
|
||||||
glBindTexture: (GLenum, GLuint);
|
|
||||||
glDrawArrays: (GLenum, GLint, GLsizei);
|
|
||||||
|
|
||||||
test_array: [10]*int;
|
|
||||||
|
|
||||||
thing : *Things;
|
|
||||||
thing_cap: S64;
|
|
||||||
thing_len: S64;
|
|
||||||
}
|
|
||||||
|
|
||||||
OS_Memory::struct{
|
|
||||||
data: *void;
|
|
||||||
commit: SizeU;
|
|
||||||
reserve: SizeU;
|
|
||||||
}
|
|
||||||
|
|
||||||
Arena::struct{
|
|
||||||
@using memory: OS_Memory;
|
|
||||||
len: U64;
|
|
||||||
alignment: U64;
|
|
||||||
}
|
|
||||||
|
|
||||||
String::struct{
|
|
||||||
str: *U8;
|
|
||||||
len: S64;
|
|
||||||
}
|
|
||||||
Intern_String::typedef = String;
|
|
||||||
//CONST_VALUE::const = 121591;
|
|
||||||
|
|
||||||
@stringify
|
|
||||||
@prefix="TK_"
|
|
||||||
Token_Kind::enum{
|
|
||||||
@str="End of stream" End,
|
|
||||||
@str="*" Mul,
|
|
||||||
@str="/" Div,
|
|
||||||
@str="+" Add,
|
|
||||||
@str="-" Sub,
|
|
||||||
@str="%" Mod,
|
|
||||||
@str="&" BitAnd,
|
|
||||||
@str="|" BitOr,
|
|
||||||
@str="^" BitXor,
|
|
||||||
@str="~" Neg,
|
|
||||||
@str="!" Not,
|
|
||||||
@str="(" OpenParen,
|
|
||||||
@str=" " CloseParen,
|
|
||||||
@str="{" OpenBrace,
|
|
||||||
@str="}" CloseBrace,
|
|
||||||
@str="[" OpenBracket,
|
|
||||||
@str="]" CloseBracket,
|
|
||||||
@str="," Comma,
|
|
||||||
@str="#" Pound,
|
|
||||||
@str="?" Question,
|
|
||||||
@str="..." ThreeDots,
|
|
||||||
@str=";" Semicolon,
|
|
||||||
@str="." Dot,
|
|
||||||
@str="<" LesserThen,
|
|
||||||
@str=">" GreaterThen,
|
|
||||||
@str=":" Colon,
|
|
||||||
@str="=" Assign,
|
|
||||||
@str="/=" DivAssign,
|
|
||||||
@str="*=" MulAssign,
|
|
||||||
@str="%=" ModAssign,
|
|
||||||
@str="-=" SubAssign,
|
|
||||||
@str="+=" AddAssign,
|
|
||||||
@str="&=" AndAssign,
|
|
||||||
@str="|=" OrAssign,
|
|
||||||
@str="^=" XorAssign,
|
|
||||||
@str="<<=" LeftShiftAssign,
|
|
||||||
@str=">>=" RightShiftAssign,
|
|
||||||
@str="::" DoubleColon,
|
|
||||||
@str="@" At,
|
|
||||||
@str="--" Decrement,
|
|
||||||
@str="++" Increment,
|
|
||||||
@str="--" PostDecrement,
|
|
||||||
@str="++" PostIncrement,
|
|
||||||
@str="<=" LesserThenOrEqual,
|
|
||||||
@str=">=" GreaterThenOrEqual,
|
|
||||||
@str="==" Equals,
|
|
||||||
@str="&&" And,
|
|
||||||
@str="||" Or,
|
|
||||||
@str="!=" NotEquals,
|
|
||||||
@str="<<" LeftShift,
|
|
||||||
@str=">>" RightShift,
|
|
||||||
@str="->" Arrow,
|
|
||||||
@str="sizeof" ExprSizeof,
|
|
||||||
DocComment,
|
|
||||||
Comment,
|
|
||||||
Identifier,
|
|
||||||
StringLit,
|
|
||||||
U8Lit,
|
|
||||||
Character,
|
|
||||||
Error,
|
|
||||||
Float,
|
|
||||||
Int,
|
|
||||||
Keyword,
|
|
||||||
}
|
|
||||||
|
|
||||||
@array(type=block)
|
|
||||||
Token::struct{
|
|
||||||
kind:Token_Kind;
|
|
||||||
@using string:String;
|
|
||||||
union{
|
|
||||||
integer_val:S64;
|
|
||||||
error_val:String;
|
|
||||||
intern_val:Intern_String;
|
|
||||||
}
|
|
||||||
file:String;
|
|
||||||
line:S64;
|
|
||||||
line_begin:*U8;
|
|
||||||
}
|
|
||||||
|
|
||||||
Lex_Stream::struct{
|
|
||||||
stream: *U8;
|
|
||||||
line_begin: *U8;
|
|
||||||
filename: String;
|
|
||||||
line: S64;
|
|
||||||
}
|
|
||||||
|
|
||||||
@prefix="EK_"
|
|
||||||
Expr_Kind::enum{
|
|
||||||
None,
|
|
||||||
Atom,
|
|
||||||
Unary,
|
|
||||||
Binary,
|
|
||||||
Ternary,
|
|
||||||
Cast,
|
|
||||||
List,
|
|
||||||
Call,
|
|
||||||
Index,
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr:: struct{
|
|
||||||
kind: Expr_Kind;
|
|
||||||
token: *Token;
|
|
||||||
next : *Expr;
|
|
||||||
union{
|
|
||||||
cast_val: struct{
|
|
||||||
type: *AST_Node;
|
|
||||||
expr: *Expr;
|
|
||||||
}
|
|
||||||
list: struct{
|
|
||||||
first: *Expr;
|
|
||||||
last: *Expr;
|
|
||||||
}
|
|
||||||
call: struct{
|
|
||||||
atom: *Expr;
|
|
||||||
list: *Expr;
|
|
||||||
}
|
|
||||||
index: struct{
|
|
||||||
atom: *Expr;
|
|
||||||
index: *Expr;
|
|
||||||
}
|
|
||||||
unary: struct{
|
|
||||||
expr: *Expr ;
|
|
||||||
}
|
|
||||||
binary: struct{
|
|
||||||
left: *Expr ;
|
|
||||||
right: *Expr ;
|
|
||||||
}
|
|
||||||
ternary: struct{
|
|
||||||
cond: *Expr ;
|
|
||||||
on_true: *Expr;
|
|
||||||
on_false: *Expr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@prefix="AK_"
|
|
||||||
AST_Kind::enum{
|
|
||||||
None,
|
|
||||||
BaseType,
|
|
||||||
Typedef,
|
|
||||||
Enum,
|
|
||||||
Struct,
|
|
||||||
Union,
|
|
||||||
Note,
|
|
||||||
List,
|
|
||||||
Pointer,
|
|
||||||
Array,
|
|
||||||
Function,
|
|
||||||
Variable,
|
|
||||||
EnumChild,
|
|
||||||
}
|
|
||||||
|
|
||||||
AST_Node::struct{
|
|
||||||
kind: AST_Kind;
|
|
||||||
pos : *Token;
|
|
||||||
name: Intern_String;
|
|
||||||
|
|
||||||
next: *AST_Node;
|
|
||||||
next_scope: *AST_Node;
|
|
||||||
|
|
||||||
first_note: *AST_Node;
|
|
||||||
last_note: *AST_Node;
|
|
||||||
|
|
||||||
first_child: *AST_Node;
|
|
||||||
last_child: *AST_Node;
|
|
||||||
union{
|
|
||||||
base_type_size: SizeU;
|
|
||||||
pointer: *AST_Node;
|
|
||||||
typedef_type: *AST_Node;
|
|
||||||
variable_type: *AST_Node;
|
|
||||||
func_return_type: *AST_Node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Parser_Error :: struct{
|
|
||||||
next: *Parser_Error;
|
|
||||||
message: String;
|
|
||||||
token : *Token;
|
|
||||||
}
|
|
||||||
|
|
||||||
Scope :: struct{
|
|
||||||
next : *Scope;
|
|
||||||
first: *AST_Node;
|
|
||||||
last : *AST_Node;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Parser :: struct{
|
|
||||||
main_arena: Arena;
|
|
||||||
intern_table_arena: Arena;
|
|
||||||
symbol_table_arena: Arena;
|
|
||||||
|
|
||||||
scope_free_list: Scope;
|
|
||||||
scope_stack: Scope;
|
|
||||||
global_scope: Scope;
|
|
||||||
|
|
||||||
symbols_inserted: S64;
|
|
||||||
symbols_count: S64;
|
|
||||||
symbols: AST_Node;
|
|
||||||
|
|
||||||
interns: Intern_String;
|
|
||||||
interns_in_bytes: S64;
|
|
||||||
interns_inserted: S64;
|
|
||||||
interns_count: S64;
|
|
||||||
|
|
||||||
first_keyword: U8;
|
|
||||||
last_keyword: U8;
|
|
||||||
|
|
||||||
//@map(type="sparse") symbols: AST_Node;
|
|
||||||
|
|
||||||
// @Todo(Krzosa): This adds default to function name currently
|
|
||||||
// And it's hard to anything else sort of except adding
|
|
||||||
// a variable of _var_name_lower_with_ or something
|
|
||||||
@sllqueue default: Parser_Error;
|
|
||||||
|
|
||||||
// This works ok
|
|
||||||
@sllqueue error: Parser_Error;
|
|
||||||
//@using token_array: Tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function_test::(a:U32, b:U32):*U32{
|
|
||||||
scratch := get_scratch();
|
|
||||||
defer{release_scratch(scratch);}
|
|
||||||
if a > 10 {
|
|
||||||
c := b + 10;
|
|
||||||
b = c;
|
|
||||||
}
|
|
||||||
else if a == 20 {
|
|
||||||
d := 1241215;
|
|
||||||
b = d;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
c := b+20;
|
|
||||||
b = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
c: U32 = b + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for i:=0; i < 10; i++ {
|
|
||||||
print(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *b;
|
|
||||||
}
|
|
||||||
31
test2.cc
31
test2.cc
@@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
Thing :: struct {
|
|
||||||
arena: *Arena;
|
|
||||||
}
|
|
||||||
|
|
||||||
main :: (argc: int, argv: **char): int {
|
|
||||||
thing: int = proc(&argc);
|
|
||||||
arena: Arena;
|
|
||||||
|
|
||||||
for i:=0; i < 10; i++ {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
proc :: (thing: *int): *int {
|
|
||||||
thing = SCRATCH_COUNT + 10;
|
|
||||||
return thing;
|
|
||||||
}
|
|
||||||
|
|
||||||
Arena :: struct {
|
|
||||||
cap: int;
|
|
||||||
len: int;
|
|
||||||
data: *void;
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread_Ctx :: struct {
|
|
||||||
arenas: [SCRATCH_COUNT]Arena;
|
|
||||||
}
|
|
||||||
SCRATCH_COUNT::const = 3;
|
|
||||||
|
|
||||||
30
test3.kl
30
test3.kl
@@ -1,7 +1,5 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
|
Player :: struct
|
||||||
Player :: struct
|
|
||||||
id : int
|
id : int
|
||||||
name: String
|
name: String
|
||||||
|
|
||||||
@@ -12,7 +10,7 @@ compound_of_struct: Player = {
|
|||||||
|
|
||||||
second_compound_syntax := :Player{...}
|
second_compound_syntax := :Player{...}
|
||||||
|
|
||||||
max :: (a: int, b: int) { if a > b then return a; return b; }
|
max_folding :: (a: int, b: int) { if a > b { return a; } return b; }
|
||||||
|
|
||||||
max :: (a: int, b: int)
|
max :: (a: int, b: int)
|
||||||
if a > b then return a
|
if a > b then return a
|
||||||
@@ -22,22 +20,34 @@ max :: (a: int, b: int)
|
|||||||
{ and } - treated as new line scope and end of new line scope
|
{ and } - treated as new line scope and end of new line scope
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Function types
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
test_function :: (thing: int): ^int
|
test_function :: (thing: int): ^int
|
||||||
|
function_type: (thing: int): ^int = test_function
|
||||||
|
const_function_alias :: test_function
|
||||||
|
null_function: (t: int): ^int = null
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Booleans
|
// Booleans
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
boolean: bool = true
|
boolean: bool = true
|
||||||
value_of_bool: int = cast(boolean: int)
|
value_of_bool: int = cast(boolean: int)
|
||||||
base := null
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Nulls
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int_null: int = null
|
||||||
|
str_null: String = null
|
||||||
|
bool_null: bool = null
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Compound expressions
|
// Compound expressions
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
array1: [4]int = {1,2,3,4}
|
array1: [4]int = {1,2,3,4}
|
||||||
array2: [32]int = {1,2,3,4}
|
array2: [32]int = {1,2,3,4}
|
||||||
array3: [32]int = {
|
array3: [32]int = {
|
||||||
[0] = 0,
|
[0] = null,
|
||||||
[1] = 1,
|
[1] = 1,
|
||||||
[31] = 31,
|
[31] = 31,
|
||||||
}
|
}
|
||||||
@@ -61,8 +71,8 @@ implicit_str :: "Hello world"
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Pointers
|
// Pointers
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
pointer: ^int = cast(null: ^int)
|
pointer1: ^int = null
|
||||||
pointer2: ^int = null
|
pointer2: ^int = pointer1
|
||||||
pointer3: ^^int = null
|
pointer3: ^^int = null
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|||||||
157
type.c
157
type.c
@@ -1,157 +0,0 @@
|
|||||||
typedef struct Type Type;
|
|
||||||
|
|
||||||
typedef enum Type_Kind{
|
|
||||||
TYPE_None,
|
|
||||||
TYPE_Incomplete,
|
|
||||||
TYPE_Int,
|
|
||||||
TYPE_Char,
|
|
||||||
TYPE_Void,
|
|
||||||
TYPE_Pointer,
|
|
||||||
TYPE_Array,
|
|
||||||
TYPE_Func,
|
|
||||||
TYPE_Struct,
|
|
||||||
TYPE_Union,
|
|
||||||
TYPE_Enum,
|
|
||||||
}Type_Kind;
|
|
||||||
|
|
||||||
struct Type{
|
|
||||||
Type_Kind kind;
|
|
||||||
SizeU size;
|
|
||||||
SizeU align;
|
|
||||||
struct{
|
|
||||||
Type *base;
|
|
||||||
}pointer;
|
|
||||||
struct{
|
|
||||||
Type *base;
|
|
||||||
SizeU size;
|
|
||||||
}array;
|
|
||||||
struct{
|
|
||||||
Type **params;
|
|
||||||
S32 count;
|
|
||||||
Type *ret;
|
|
||||||
}func;
|
|
||||||
};
|
|
||||||
|
|
||||||
global Type global_type[] = {
|
|
||||||
{TYPE_Void},
|
|
||||||
{TYPE_Int, sizeof(int), __alignof(int)},
|
|
||||||
{TYPE_Char, sizeof(char), __alignof(char)},
|
|
||||||
};
|
|
||||||
|
|
||||||
const SizeU pointer_size = sizeof(SizeU);
|
|
||||||
const SizeU pointer_align = __alignof(SizeU);
|
|
||||||
|
|
||||||
global Type *type_void = global_type + 0;
|
|
||||||
global Type *type_int = global_type + 1;
|
|
||||||
global Type *type_char = global_type + 2;
|
|
||||||
|
|
||||||
global Map map_pointer_types;
|
|
||||||
global Map map_array_types;
|
|
||||||
global Map map_func_types;
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_new(Arena *arena, Type_Kind kind, SizeU size, SizeU align){
|
|
||||||
Type *result = arena_push_struct(arena, Type);
|
|
||||||
result->kind = kind;
|
|
||||||
result->size = size;
|
|
||||||
result->align = align;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_copy(Arena *arena, Type *type){
|
|
||||||
Type *result = arena_push_struct(arena, Type);
|
|
||||||
memory_copy(result, type, sizeof(Type));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_incomplete(Arena *arena){
|
|
||||||
Type *result = type_new(arena, TYPE_Incomplete, 0, 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_pointer(Arena *arena, Type *base){
|
|
||||||
Type *result = map_get(&map_pointer_types, (void *)base);
|
|
||||||
if(!result){
|
|
||||||
result = type_new(arena, TYPE_Pointer, pointer_size, pointer_align);
|
|
||||||
result->pointer.base = base;
|
|
||||||
map_insert(&map_pointer_types, base, result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_array(Arena *arena, Type *base, SizeU size){
|
|
||||||
U64 hash = hash_mix(hash_ptr(base), hash_u64(size));
|
|
||||||
Type *result = map_get_u64(&map_array_types, hash);
|
|
||||||
if(result){
|
|
||||||
assert(result->array.size == size);
|
|
||||||
assert(result->array.base == base);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = type_new(arena, TYPE_Array, pointer_size, pointer_align);
|
|
||||||
result->array.base = base;
|
|
||||||
result->array.size = size;
|
|
||||||
map_insert_u64(&map_array_types, hash, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_lambda(Arena *arena, Type *ret, Type **params, S32 count){
|
|
||||||
U64 hash = hash_ptr(ret);
|
|
||||||
for(S32 i = 0; i < count; i++)
|
|
||||||
hash = hash_mix(hash, hash_ptr(params[i]));
|
|
||||||
|
|
||||||
Type *result = map_get_u64(&map_func_types, hash);
|
|
||||||
if(result){
|
|
||||||
assert(result->func.ret == ret);
|
|
||||||
assert(result->func.count == count);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = type_new(arena, TYPE_Func, pointer_size, pointer_align);
|
|
||||||
result->func.ret = ret;
|
|
||||||
result->func.count = count;
|
|
||||||
result->func.params = arena_push_array(arena, Type*, count);
|
|
||||||
memory_copy(result->func.params, params, count);
|
|
||||||
map_insert_u64(&map_func_types, hash, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function void
|
|
||||||
test_types(){
|
|
||||||
Arena *arena = arena_begin_scratch();
|
|
||||||
Type *array_type1 = type_array(arena, type_int, 32);
|
|
||||||
Type *array_type2 = type_array(arena, type_int, 32);
|
|
||||||
Type *array_type3 = type_array(arena, type_int, 48);
|
|
||||||
assert(array_type1 == array_type2);
|
|
||||||
assert(array_type2 != array_type3);
|
|
||||||
Type *pointer_type1 = type_pointer(arena, type_int);
|
|
||||||
Type *pointer_type2 = type_pointer(arena, type_int);
|
|
||||||
assert(pointer_type2 == pointer_type1);
|
|
||||||
Type *pointer_type3 = type_pointer(arena, pointer_type1);
|
|
||||||
Type *pointer_type4 = type_pointer(arena, pointer_type2);
|
|
||||||
assert(pointer_type3 != pointer_type1);
|
|
||||||
assert(pointer_type3 == pointer_type4);
|
|
||||||
|
|
||||||
Type **types = 0;
|
|
||||||
array_push(types, type_array(arena, type_int, 32));
|
|
||||||
Type *func_type1 = type_lambda(arena, types[0], types, array_len(types));
|
|
||||||
Type *func_type2 = type_lambda(arena, types[0], types, array_len(types));
|
|
||||||
assert(func_type1 == func_type2);
|
|
||||||
|
|
||||||
Type **types2 = 0;
|
|
||||||
{
|
|
||||||
array_push(types2, type_array(arena, type_int, 32));
|
|
||||||
array_push(types2, type_int);
|
|
||||||
}
|
|
||||||
array_push(types, type_int);
|
|
||||||
Type *func_type3 = type_lambda(arena, types[0], types, array_len(types));
|
|
||||||
Type *func_type4 = type_lambda(arena, types[0], types2, array_len(types));
|
|
||||||
assert(func_type1 != func_type3);
|
|
||||||
assert(func_type3 == func_type4);
|
|
||||||
|
|
||||||
arena_end_scratch();
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user