Generating valid c code, more work on null values
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
@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){
|
||||
keyword_if = intern_string(t, lit("if"));
|
||||
first_keyword = keyword_if.s.str;
|
||||
|
||||
|
||||
keyword_cast = intern_string(t, lit("cast"));
|
||||
keyword_for = intern_string(t, lit("for"));
|
||||
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_struct = intern_string(t, lit("struct"));
|
||||
keyword_enum = intern_string(t, lit("enum"));
|
||||
|
||||
|
||||
keyword_union = intern_string(t, lit("union"));
|
||||
last_keyword = keyword_union.s.str;
|
||||
|
||||
|
||||
intern_char = intern_string(t, lit("char"));
|
||||
intern_void = intern_string(t, lit("void"));
|
||||
intern_int = intern_string(t, lit("int"));
|
||||
}
|
||||
|
||||
function B32
|
||||
function B32
|
||||
lex_is_keyword(Intern_String str){
|
||||
B32 result = str.s.str >= first_keyword && str.s.str <= last_keyword;
|
||||
return result;
|
||||
@@ -61,7 +61,7 @@ lex_is_keyword(Intern_String str){
|
||||
|
||||
typedef enum Token_Kind{
|
||||
TK_End,
|
||||
|
||||
|
||||
TK_Mul,
|
||||
TK_Div,
|
||||
TK_Mod,
|
||||
@@ -69,12 +69,12 @@ typedef enum Token_Kind{
|
||||
TK_RightShift,
|
||||
TK_FirstMul = TK_Mul,
|
||||
TK_LastMul = TK_RightShift,
|
||||
|
||||
|
||||
TK_Add,
|
||||
TK_Sub,
|
||||
TK_FirstAdd = TK_Add,
|
||||
TK_LastAdd = TK_Sub,
|
||||
|
||||
|
||||
TK_Equals,
|
||||
TK_LesserThenOrEqual,
|
||||
TK_GreaterThenOrEqual,
|
||||
@@ -83,15 +83,15 @@ typedef enum Token_Kind{
|
||||
TK_NotEquals,
|
||||
TK_FirstCompare = TK_Equals,
|
||||
TK_LastCompare = TK_NotEquals,
|
||||
|
||||
|
||||
TK_BitAnd,
|
||||
TK_BitOr,
|
||||
TK_BitXor,
|
||||
TK_Pointer,
|
||||
TK_And,
|
||||
TK_Or,
|
||||
TK_FirstLogical = TK_BitAnd,
|
||||
TK_LastLogical = TK_Or,
|
||||
|
||||
|
||||
TK_Neg,
|
||||
TK_Not,
|
||||
TK_OpenParen,
|
||||
@@ -106,9 +106,9 @@ typedef enum Token_Kind{
|
||||
TK_ThreeDots,
|
||||
TK_Semicolon,
|
||||
TK_Dot,
|
||||
|
||||
|
||||
TK_Colon,
|
||||
|
||||
|
||||
TK_Assign,
|
||||
TK_ColonAssign,
|
||||
TK_DivAssign,
|
||||
@@ -123,14 +123,14 @@ typedef enum Token_Kind{
|
||||
TK_RightShiftAssign,
|
||||
TK_FirstAssign = TK_Assign,
|
||||
TK_LastAssign = TK_RightShiftAssign,
|
||||
|
||||
|
||||
TK_DoubleColon,
|
||||
TK_At,
|
||||
TK_Decrement,
|
||||
TK_Increment,
|
||||
TK_PostDecrement,
|
||||
TK_PostIncrement,
|
||||
|
||||
|
||||
TK_Arrow,
|
||||
TK_ExprSizeof,
|
||||
TK_DocComment,
|
||||
@@ -150,14 +150,14 @@ typedef struct Token{
|
||||
String string;
|
||||
struct{U8 *str; S64 len;};
|
||||
};
|
||||
|
||||
|
||||
union {
|
||||
U64 int_val;
|
||||
F64 float_val;
|
||||
String error_val;
|
||||
Intern_String intern_val;
|
||||
};
|
||||
|
||||
|
||||
String file;
|
||||
S32 line;
|
||||
U8 *line_begin;
|
||||
@@ -167,7 +167,7 @@ typedef struct Token{
|
||||
typedef struct Lex_Stream{
|
||||
String stream;
|
||||
S64 iter;
|
||||
|
||||
|
||||
U8 *line_begin;
|
||||
String file;
|
||||
S32 line;
|
||||
@@ -207,7 +207,7 @@ lex_is_numeric(U8 c){
|
||||
return result;
|
||||
}
|
||||
|
||||
function B32
|
||||
function B32
|
||||
lex_is_alphanumeric(U8 c){
|
||||
B32 result = lex_is_numeric(c) || lex_is_alphabetic(c);
|
||||
return result;
|
||||
@@ -226,7 +226,7 @@ token_error(Token *t, String error_val){
|
||||
}
|
||||
|
||||
function void
|
||||
lex_parse_u64(Token *t){
|
||||
lex_parse_u64(Token *t){
|
||||
U64 result = 0;
|
||||
U64 m = 1;
|
||||
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){
|
||||
for(;;){
|
||||
if(lexc(s) == '\\') lex_advance(s);
|
||||
@@ -301,14 +301,14 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
||||
while(lexc(s)){
|
||||
while(lex_is_whitespace(lexc(s)))
|
||||
lex_advance(s);
|
||||
|
||||
|
||||
Token t = {0};
|
||||
t.str = lexcp(s);
|
||||
t.file = s->file;
|
||||
t.line = s->line;
|
||||
t.line_begin = s->line_begin;
|
||||
lex_advance(s);
|
||||
|
||||
|
||||
switch(*t.str){
|
||||
case 0: 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_Pound; break;
|
||||
CASE2('!', TK_Not, TK_NotEquals);
|
||||
CASE2('^', TK_BitXor, TK_XorAssign);
|
||||
CASE2('^', TK_Pointer, TK_XorAssign);
|
||||
CASE2('=', TK_Assign, TK_Equals);
|
||||
CASE2('*', TK_Mul, TK_MulAssign);
|
||||
CASE2('%', TK_Mod, TK_ModAssign);
|
||||
@@ -342,8 +342,8 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
||||
t.kind = TK_Dot;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
|
||||
|
||||
case '<': {
|
||||
if (lexc(s) == '<') {
|
||||
lex_advance(s);
|
||||
@@ -363,7 +363,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
||||
t.kind = TK_LesserThen;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
case '>': {
|
||||
if (lexc(s) == '>') {
|
||||
lex_advance(s);
|
||||
@@ -383,7 +383,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
||||
t.kind = TK_GreaterThen;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
case ':': {
|
||||
if (lexc(s) == ':') {
|
||||
lex_advance(s);
|
||||
@@ -397,7 +397,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
||||
t.kind = TK_Colon;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
case '-':{
|
||||
if (lexc(s) == '=') {
|
||||
lex_advance(s);
|
||||
@@ -415,11 +415,11 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
||||
t.kind = TK_Sub;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
|
||||
|
||||
case '\'':{not_implemented;} break;
|
||||
case '"': {
|
||||
t.kind = TK_StringLit;
|
||||
t.kind = TK_StringLit;
|
||||
lex_parse_string(s,&t,'"');
|
||||
if(t.kind != TK_Error){
|
||||
t.str += 1;
|
||||
@@ -427,7 +427,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
||||
}
|
||||
t.intern_val = intern_string(&array->interns, t.string);
|
||||
} break;
|
||||
|
||||
|
||||
case '/': {
|
||||
if(lexc(s) == '='){
|
||||
t.kind = TK_DivAssign;
|
||||
@@ -464,7 +464,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
||||
t.kind = TK_Div;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
case '0':case '1':case '2':case '3':case '4':
|
||||
case '5':case '6':case '7':case '8':case '9':{
|
||||
t.kind = TK_Integer;
|
||||
@@ -473,7 +473,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
||||
lex_set_len(s, &t);
|
||||
lex_parse_u64(&t);
|
||||
} break;
|
||||
|
||||
|
||||
case 'A':case 'a':case 'M':case 'm':case 'B':
|
||||
case 'b':case 'N':case 'n':case 'C':case 'c':case 'O':
|
||||
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;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
default: {
|
||||
token_error(&t, lit("Unknown token"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(t.len==0)
|
||||
lex_set_len(s,&t);
|
||||
|
||||
|
||||
token_array_push(array, &t);
|
||||
}
|
||||
}
|
||||
@@ -538,13 +538,13 @@ lex_test(){
|
||||
"\"Test_Meme\"+=-===42524 4294967295 18446744073709551615"
|
||||
"for if while switch :=");
|
||||
Token_Array array = lex_stream(scratch, test, lit("Test1"));
|
||||
|
||||
|
||||
Token_Kind kind[] = {
|
||||
TK_Error,TK_OpenBrace,TK_CloseBrace,TK_CloseParen,TK_OpenParen,
|
||||
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_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
|
||||
};
|
||||
String strs[] = {
|
||||
@@ -558,7 +558,7 @@ lex_test(){
|
||||
U64 vals[] = {
|
||||
42524, 4294967295, 18446744073709551615llu
|
||||
};
|
||||
|
||||
|
||||
int i = 0;
|
||||
int ui = 0;
|
||||
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();
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -584,7 +584,7 @@ global const char *token_kind_string[] = {
|
||||
[TK_Mod] = "%",
|
||||
[TK_BitAnd] = "&",
|
||||
[TK_BitOr] = "|",
|
||||
[TK_BitXor] = "^",
|
||||
[TK_Pointer] = "^",
|
||||
[TK_Neg] = "~",
|
||||
[TK_Not] = "!",
|
||||
[TK_OpenParen] = "(",
|
||||
|
||||
7
main.cpp
7
main.cpp
@@ -5,21 +5,20 @@
|
||||
#include "new_parse.cpp"
|
||||
#include "new_type.cpp"
|
||||
#include "new_resolve.cpp"
|
||||
#include "cgenerate.cpp"
|
||||
|
||||
int main(){
|
||||
test_os_memory();
|
||||
thread_ctx_init();
|
||||
|
||||
test_gen();
|
||||
test_unicode();
|
||||
test_resolve();
|
||||
test_types();
|
||||
test_parse_expr();
|
||||
|
||||
|
||||
map_test();
|
||||
test_array();
|
||||
test_string_builder();
|
||||
test_intern_table();
|
||||
lex_test();
|
||||
}
|
||||
|
||||
|
||||
|
||||
50
new_ast.cpp
50
new_ast.cpp
@@ -4,7 +4,7 @@
|
||||
//
|
||||
// Parser::ast_arena - arena for asts
|
||||
// Lexer::interns::string_allocator - arena for interns
|
||||
//
|
||||
//
|
||||
Intern_String keyword_struct;
|
||||
Intern_String keyword_union;
|
||||
Intern_String keyword_cast;
|
||||
@@ -19,21 +19,25 @@ const U64 Parse_Ctx_ID = 115151;
|
||||
struct Parse_Ctx:Lexer{
|
||||
Allocator *perm; // Stores: AST, tokens, interns
|
||||
Allocator *heap;
|
||||
|
||||
|
||||
U64 unique_ids;
|
||||
Map global_syms;
|
||||
Map type_map;
|
||||
|
||||
|
||||
Token empty_token;
|
||||
S64 indent;
|
||||
|
||||
|
||||
Intern_String intern(String string){
|
||||
return intern_string(&interns, string);
|
||||
}
|
||||
|
||||
void init(Allocator *perm_allocator, Allocator *heap_allocator){
|
||||
perm = perm_allocator;
|
||||
heap = heap_allocator;
|
||||
|
||||
|
||||
global_syms = {heap};
|
||||
type_map = {heap};
|
||||
|
||||
|
||||
lex_init(perm, heap, this);
|
||||
keyword_struct= intern_string(&interns, "struct"_s);
|
||||
keyword_union = intern_string(&interns, "union"_s);
|
||||
@@ -41,7 +45,7 @@ struct Parse_Ctx:Lexer{
|
||||
keyword_enum = intern_string(&interns, "enum"_s);
|
||||
interns.first_keyword = keyword_struct.str;
|
||||
interns.last_keyword = keyword_enum.str;
|
||||
|
||||
|
||||
intern_void = intern_string(&interns, "void"_s);
|
||||
intern_int = intern_string(&interns, "int"_s);
|
||||
intern_str = intern_string(&interns, "String"_s);
|
||||
@@ -55,9 +59,9 @@ thread_local Parse_Ctx *pctx;
|
||||
//-----------------------------------------------------------------------------
|
||||
enum Ast_Kind{
|
||||
AST_NONE,
|
||||
|
||||
|
||||
AST_PACKAGE,
|
||||
|
||||
|
||||
AST_STR,
|
||||
AST_INT,
|
||||
AST_CAST,
|
||||
@@ -67,12 +71,12 @@ enum Ast_Kind{
|
||||
AST_BINARY,
|
||||
AST_COMPOUND_ITEM,
|
||||
AST_COMPOUND,
|
||||
|
||||
|
||||
AST_LAMBDA,
|
||||
AST_LAMBDA_PARAM,
|
||||
AST_CONST,
|
||||
AST_VAR,
|
||||
|
||||
|
||||
AST_TYPESPEC_IDENT,
|
||||
AST_TYPESPEC_POINTER,
|
||||
AST_TYPESPEC_ARRAY,
|
||||
@@ -85,6 +89,7 @@ struct Ast{
|
||||
Token *pos;
|
||||
};
|
||||
|
||||
struct Ast_Resolved_Type;
|
||||
struct Ast_Typespec;
|
||||
struct Ast_Expr:Ast{
|
||||
union{
|
||||
@@ -94,13 +99,13 @@ struct Ast_Expr:Ast{
|
||||
Token_Kind op;
|
||||
Ast_Expr *expr;
|
||||
}unary;
|
||||
|
||||
struct{
|
||||
Token_Kind op;
|
||||
Ast_Expr *left;
|
||||
Ast_Expr *right;
|
||||
} binary;
|
||||
struct{
|
||||
Ast_Resolved_Type *type;
|
||||
Ast_Typespec *typespec;
|
||||
Array<Ast_Expr *> exprs;
|
||||
}compound;
|
||||
@@ -124,12 +129,19 @@ struct Ast_Expr:Ast{
|
||||
};
|
||||
};
|
||||
|
||||
struct Ast_Block : Ast {
|
||||
Array<Ast *> stmts;
|
||||
};
|
||||
|
||||
struct Ast_Lambda : Ast_Expr {
|
||||
Array<Ast_Expr *> params;
|
||||
Ast_Typespec *ret;
|
||||
Ast_Block *block;
|
||||
};
|
||||
|
||||
struct Ast_Resolved_Type;
|
||||
struct Ast_Typespec:Ast{
|
||||
Ast_Resolved_Type *resolved_type;
|
||||
union{
|
||||
Ast_Typespec *base;
|
||||
Intern_String name;
|
||||
@@ -148,10 +160,6 @@ struct Ast_Decl:Ast{
|
||||
Ast_Typespec *typespec;
|
||||
Ast_Expr *expr;
|
||||
}var;
|
||||
struct{
|
||||
Array<Ast_Decl*> args;
|
||||
Ast_Typespec *ret;
|
||||
}func;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -164,10 +172,10 @@ struct Ast_Package:Ast{
|
||||
// AST Constructors beginning with expressions
|
||||
//-----------------------------------------------------------------------------
|
||||
#define AST_NEW(T,ikind,ipos) \
|
||||
Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \
|
||||
result->kind = ikind; \
|
||||
result->pos = ipos; \
|
||||
result->id = ++pctx->unique_ids
|
||||
Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \
|
||||
result->kind = ikind; \
|
||||
result->pos = ipos; \
|
||||
result->id = ++pctx->unique_ids
|
||||
|
||||
function Ast_Expr *
|
||||
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->name = intern_string(&pctx->interns, name);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
152
new_lex.cpp
152
new_lex.cpp
@@ -1,7 +1,7 @@
|
||||
|
||||
enum Token_Kind{
|
||||
TK_End,
|
||||
|
||||
|
||||
TK_Mul,
|
||||
TK_Div,
|
||||
TK_Mod,
|
||||
@@ -9,12 +9,12 @@ enum Token_Kind{
|
||||
TK_RightShift,
|
||||
TK_FirstMul = TK_Mul,
|
||||
TK_LastMul = TK_RightShift,
|
||||
|
||||
|
||||
TK_Add,
|
||||
TK_Sub,
|
||||
TK_FirstAdd = TK_Add,
|
||||
TK_LastAdd = TK_Sub,
|
||||
|
||||
|
||||
TK_Equals,
|
||||
TK_LesserThenOrEqual,
|
||||
TK_GreaterThenOrEqual,
|
||||
@@ -23,15 +23,14 @@ enum Token_Kind{
|
||||
TK_NotEquals,
|
||||
TK_FirstCompare = TK_Equals,
|
||||
TK_LastCompare = TK_NotEquals,
|
||||
|
||||
|
||||
TK_BitAnd,
|
||||
TK_BitOr,
|
||||
TK_BitXor,
|
||||
TK_And,
|
||||
TK_Or,
|
||||
TK_FirstLogical = TK_BitAnd,
|
||||
TK_LastLogical = TK_Or,
|
||||
|
||||
|
||||
TK_Neg,
|
||||
TK_Not,
|
||||
TK_OpenParen,
|
||||
@@ -46,10 +45,10 @@ enum Token_Kind{
|
||||
TK_ThreeDots,
|
||||
TK_Semicolon,
|
||||
TK_Dot,
|
||||
|
||||
|
||||
TK_NewLine,
|
||||
TK_Colon,
|
||||
|
||||
|
||||
TK_Assign,
|
||||
TK_DivAssign,
|
||||
TK_MulAssign,
|
||||
@@ -63,14 +62,14 @@ enum Token_Kind{
|
||||
TK_RightShiftAssign,
|
||||
TK_FirstAssign = TK_Assign,
|
||||
TK_LastAssign = TK_RightShiftAssign,
|
||||
|
||||
|
||||
TK_DoubleColon,
|
||||
TK_At,
|
||||
TK_Decrement,
|
||||
TK_Increment,
|
||||
TK_PostDecrement,
|
||||
TK_PostIncrement,
|
||||
|
||||
|
||||
TK_Arrow,
|
||||
TK_ExprSizeof,
|
||||
TK_DocComment,
|
||||
@@ -82,8 +81,8 @@ enum Token_Kind{
|
||||
TK_Float,
|
||||
TK_Integer,
|
||||
TK_Keyword,
|
||||
|
||||
TK_Pointer = TK_BitXor,
|
||||
|
||||
TK_Pointer,
|
||||
TK_Dereference,
|
||||
};
|
||||
|
||||
@@ -93,7 +92,7 @@ struct Token{
|
||||
String string;
|
||||
struct{U8 *str; S64 len;};
|
||||
};
|
||||
|
||||
|
||||
union {
|
||||
U64 int_val;
|
||||
F64 float_val;
|
||||
@@ -101,7 +100,7 @@ struct Token{
|
||||
Intern_String intern_val;
|
||||
S64 indent;
|
||||
};
|
||||
|
||||
|
||||
String file;
|
||||
S32 line;
|
||||
U8 *line_begin;
|
||||
@@ -110,7 +109,7 @@ struct Token{
|
||||
struct Lex_Stream{
|
||||
String stream;
|
||||
S64 iter;
|
||||
|
||||
|
||||
U8 *line_begin;
|
||||
String file;
|
||||
S32 line;
|
||||
@@ -157,7 +156,7 @@ lex_is_numeric(U8 c){
|
||||
return result;
|
||||
}
|
||||
|
||||
function B32
|
||||
function B32
|
||||
lex_is_alphanumeric(U8 c){
|
||||
B32 result = lex_is_numeric(c) || lex_is_alphabetic(c);
|
||||
return result;
|
||||
@@ -172,9 +171,9 @@ lex_set_len(Lex_Stream *s, Token *token){
|
||||
function void
|
||||
lex_set_keywords(Lexer *lexer, Array<String> keywords){
|
||||
Intern_String keyword = {};
|
||||
Iter(keywords){
|
||||
For(keywords){
|
||||
keyword = intern_string(&lexer->interns, *it);
|
||||
if(it == keywords.begin())
|
||||
if(it == keywords.begin())
|
||||
lexer->interns.first_keyword = keyword.str;
|
||||
}
|
||||
lexer->interns.last_keyword = keyword.str;
|
||||
@@ -193,7 +192,7 @@ token_error(Token *t, String error_val){
|
||||
}
|
||||
|
||||
function void
|
||||
lex_parse_u64(Token *t){
|
||||
lex_parse_u64(Token *t){
|
||||
U64 result = 0;
|
||||
U64 m = 1;
|
||||
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){
|
||||
for(;;){
|
||||
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) \
|
||||
case op: \
|
||||
if (lexc(s) == '=') { \
|
||||
lex_advance(s); \
|
||||
t.kind = Assign; \
|
||||
} else { \
|
||||
t.kind = OpName; \
|
||||
} \
|
||||
break
|
||||
#define CASE3(op, OpName, Assign, Incr) \
|
||||
case op: \
|
||||
if (lexc(s) == '=') { \
|
||||
lex_advance(s); \
|
||||
t.kind = Assign; \
|
||||
} else if (lexc(s) == op) { \
|
||||
lex_advance(s); \
|
||||
t.kind = Incr; \
|
||||
} else { \
|
||||
t.kind = OpName; \
|
||||
} \
|
||||
break
|
||||
#define CASE2(op, OpName, Assign) \
|
||||
case op: \
|
||||
if (lexc(s) == '=') { \
|
||||
lex_advance(s); \
|
||||
t.kind = Assign; \
|
||||
} else { \
|
||||
t.kind = OpName; \
|
||||
} \
|
||||
break
|
||||
#define CASE3(op, OpName, Assign, Incr) \
|
||||
case op: \
|
||||
if (lexc(s) == '=') { \
|
||||
lex_advance(s); \
|
||||
t.kind = Assign; \
|
||||
} else if (lexc(s) == op) { \
|
||||
lex_advance(s); \
|
||||
t.kind = Incr; \
|
||||
} else { \
|
||||
t.kind = OpName; \
|
||||
} \
|
||||
break
|
||||
|
||||
function void
|
||||
lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
while(lexc(s)){
|
||||
|
||||
|
||||
Token t = {};
|
||||
t.str = lexcp(s);
|
||||
t.file = s->file;
|
||||
t.line = s->line;
|
||||
t.line_begin = s->line_begin;
|
||||
lex_advance(s);
|
||||
|
||||
|
||||
switch(*t.str){
|
||||
case 0 : 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_Question; break;
|
||||
case '#': t.kind = TK_Pound; break;
|
||||
case '^': t.kind = TK_Pointer; break;
|
||||
CASE2('!', TK_Not, TK_NotEquals);
|
||||
CASE2('^', TK_BitXor, TK_XorAssign);
|
||||
CASE2('=', TK_Assign, TK_Equals);
|
||||
CASE2('*', TK_Mul, TK_MulAssign);
|
||||
CASE2('%', TK_Mod, TK_ModAssign);
|
||||
@@ -298,15 +297,15 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
#undef CASE2
|
||||
#undef CASE3
|
||||
case ';': {
|
||||
t.kind = TK_Semicolon;
|
||||
t.kind = TK_Semicolon;
|
||||
}break;
|
||||
|
||||
|
||||
case ' ' : s->stream.str -= 1;
|
||||
case '\n': {
|
||||
t.kind = TK_NewLine;
|
||||
if(lexc(s) == '\r')
|
||||
if(lexc(s) == '\r')
|
||||
lex_advance(s);
|
||||
|
||||
|
||||
for(;;){
|
||||
if(lexc(s) == ' ') {
|
||||
t.indent++;
|
||||
@@ -316,7 +315,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
else break;
|
||||
lex_advance(s);
|
||||
}
|
||||
|
||||
|
||||
}break;
|
||||
case '.': {
|
||||
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;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
|
||||
|
||||
case '<': {
|
||||
if (lexc(s) == '<') {
|
||||
lex_advance(s);
|
||||
@@ -348,7 +347,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
t.kind = TK_LesserThen;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
case '>': {
|
||||
if (lexc(s) == '>') {
|
||||
lex_advance(s);
|
||||
@@ -368,7 +367,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
t.kind = TK_GreaterThen;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
case ':': {
|
||||
if (lexc(s) == ':') {
|
||||
lex_advance(s);
|
||||
@@ -378,7 +377,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
t.kind = TK_Colon;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
case '-':{
|
||||
if (lexc(s) == '=') {
|
||||
lex_advance(s);
|
||||
@@ -396,11 +395,11 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
t.kind = TK_Sub;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
|
||||
|
||||
case '\'':{not_implemented;} break;
|
||||
case '"': {
|
||||
t.kind = TK_StringLit;
|
||||
t.kind = TK_StringLit;
|
||||
lex_parse_string(s,&t,'"');
|
||||
if(t.kind != TK_Error){
|
||||
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);
|
||||
} break;
|
||||
|
||||
|
||||
case '/': {
|
||||
if(lexc(s) == '='){
|
||||
t.kind = TK_DivAssign;
|
||||
@@ -445,7 +444,7 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||
t.kind = TK_Div;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
case '0':case '1':case '2':case '3':case '4':
|
||||
case '5':case '6':case '7':case '8':case '9':{
|
||||
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_parse_u64(&t);
|
||||
} break;
|
||||
|
||||
|
||||
case 'A':case 'a':case 'M':case 'm':case 'B':
|
||||
case 'b':case 'N':case 'n':case 'C':case 'c':case 'O':
|
||||
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;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
default: {
|
||||
token_error(&t, "Unknown token"_s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(t.len==0)
|
||||
lex_set_len(s,&t);
|
||||
|
||||
|
||||
B32 skip = t.kind == TK_NewLine && s->inside_brace_paren > 0;
|
||||
if(!skip){
|
||||
array->add(t);
|
||||
}
|
||||
|
||||
|
||||
while(lex_is_whitespace(lexc(s)))
|
||||
lex_advance(s);
|
||||
|
||||
|
||||
if(s->iter >= s->stream.len) // End of stream
|
||||
break;
|
||||
}
|
||||
@@ -510,7 +509,12 @@ lex_make(Allocator *token_string_arena, Allocator *map_allocator){
|
||||
|
||||
function void
|
||||
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->token_iter = 0;
|
||||
lex__stream(&lexer->interns, &lexer->tokens, &lexer->stream);
|
||||
@@ -529,26 +533,26 @@ lex_test(){
|
||||
String test = "Keyword //R\n 18446744073709551616{})(@?&+-;....->,:::/**/\"Thing\" Thingy"
|
||||
"\"Test_Meme\"+=-===42524 4294967295 18446744073709551615"
|
||||
"for if while switch :="_s;
|
||||
|
||||
|
||||
Array<String> keywords = {scratch};
|
||||
keywords.add("Keyword"_s);
|
||||
keywords.add("for"_s);
|
||||
keywords.add("if"_s);
|
||||
keywords.add("while"_s);
|
||||
keywords.add("switch"_s);
|
||||
|
||||
|
||||
Lexer lexer = lex_make(scratch, scratch);
|
||||
lex_set_keywords(&lexer, keywords);
|
||||
lex_restream(&lexer, test, "Test1"_s);
|
||||
Array<Token> arr = lexer.tokens;
|
||||
|
||||
|
||||
Token_Kind kind[] = {
|
||||
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_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon,
|
||||
TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign,
|
||||
TK_Equals, TK_Integer, TK_Integer, TK_Integer,
|
||||
TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword,
|
||||
TK_Equals, TK_Integer, TK_Integer, TK_Integer,
|
||||
TK_Keyword, TK_Keyword, TK_Keyword, TK_Keyword,
|
||||
TK_Colon, TK_Assign, TK_End
|
||||
};
|
||||
String strs[] = {
|
||||
@@ -562,7 +566,7 @@ lex_test(){
|
||||
U64 vals[] = {
|
||||
42524, 4294967295, 18446744073709551615llu
|
||||
};
|
||||
|
||||
|
||||
int ui = 0;
|
||||
For(arr){
|
||||
assert(it->kind == kind[i]);
|
||||
@@ -576,7 +580,7 @@ lex_test(){
|
||||
//-----------------------------------------------------------------------------
|
||||
// Token metadata
|
||||
//-----------------------------------------------------------------------------
|
||||
function String
|
||||
function String
|
||||
token_kind_string(Token_Kind kind){
|
||||
switch(kind){
|
||||
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_BitAnd: return "&"_s;
|
||||
case TK_BitOr: return "|"_s;
|
||||
case TK_BitXor: return "^"_s;
|
||||
case TK_Pointer: return "^"_s;
|
||||
case TK_Neg: return "~"_s;
|
||||
case TK_Not: return "!"_s;
|
||||
case TK_OpenParen: return "("_s;
|
||||
|
||||
@@ -9,12 +9,12 @@ token_get(S64 i = 0){
|
||||
if(result->kind == TK_NewLine){
|
||||
pctx->indent = result->indent;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function Token *
|
||||
token_next(){
|
||||
token_next(){
|
||||
Token *token = token_get();
|
||||
pctx->token_iter++;
|
||||
return token;
|
||||
@@ -51,28 +51,28 @@ token_match_keyword(Intern_String string){
|
||||
}
|
||||
|
||||
function void
|
||||
parsing_error(Token *token, const char *str, ...){
|
||||
parsing_error(Token *token, const char *str, ...){
|
||||
Scratch scratch;
|
||||
STRING_FMT(scratch, str, string);
|
||||
|
||||
|
||||
// @Note(Krzosa): Print nice error message
|
||||
printf("\nError: %s", string.str);
|
||||
if(token){
|
||||
printf(" %s:%d\n", token->file.str, (S32)token->line);
|
||||
|
||||
|
||||
// @Note(Krzosa): Print error line
|
||||
{
|
||||
int i = 0;
|
||||
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
|
||||
printf("%.*s\n", i, token->line_begin);
|
||||
|
||||
|
||||
// @Note(Krzosa): Print error marker
|
||||
int token_i = token->str - token->line_begin;
|
||||
for(int i = 0; i < token_i-2; i++) printf(" ");
|
||||
printf("^^^^^^\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
@@ -97,15 +97,15 @@ compare = == | != | >= | > | <= | <
|
||||
logical = [&|^] | && | ||
|
||||
unary = [&*-!~+] | ++ | --
|
||||
|
||||
atom_expr = Int
|
||||
| Float
|
||||
| String
|
||||
atom_expr = Int
|
||||
| Float
|
||||
| String
|
||||
| Identifier
|
||||
| 'cast' '(' typespec ',' expr ')'
|
||||
| 'size_type' '(' typespec ')'
|
||||
| 'size_expr' '(' expr ')'
|
||||
| '{' compound_expr '}'
|
||||
| '(' expr ')'
|
||||
| '(' expr ')'
|
||||
| '(' ':' typespec ')' '{' compound_expr '}'
|
||||
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
|
||||
unary_expr = unary ? unary_expr : atom_expr
|
||||
@@ -143,17 +143,17 @@ parse_expr_compound(){
|
||||
name = ast_expr_identifier(token, token->intern_val);
|
||||
token_expect(TK_Assign);
|
||||
}
|
||||
|
||||
|
||||
Ast_Expr *item = parse_expr();
|
||||
Ast_Expr *item_comp = ast_expr_compound_item(token, index, name, item);
|
||||
exprs.add(item_comp);
|
||||
|
||||
|
||||
if(!token_match(TK_Comma)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
token_expect(TK_CloseBrace);
|
||||
|
||||
|
||||
Ast_Expr *result = ast_expr_compound(pos, 0, exprs);
|
||||
return result;
|
||||
}
|
||||
@@ -165,14 +165,24 @@ parse_optional_type(){
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
function Ast_Block *
|
||||
parse_block(){
|
||||
Ast_Block *result = 0;
|
||||
if(token_match(TK_NewScope)){
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
function Ast_Lambda *
|
||||
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;
|
||||
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
|
||||
// and this routine only fires when we have situation
|
||||
// and this routine only fires when we have situation
|
||||
// with at least one parameter
|
||||
for(;;){
|
||||
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_Expr *param = ast_expr_lambda_param(name, name->intern_val, typespec);
|
||||
params.add(param);
|
||||
|
||||
|
||||
if(!token_match(TK_Comma)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
token_expect(TK_CloseParen);
|
||||
|
||||
//Ast_Block *block = parse_block();
|
||||
Ast_Lambda *result = ast_lambda(token, params, parse_optional_type());
|
||||
return result;
|
||||
}
|
||||
@@ -196,7 +208,7 @@ null_denotation(Token *token){
|
||||
case TK_StringLit : return ast_expr_string(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_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: {
|
||||
if(token->intern_val == keyword_cast){
|
||||
token_expect(TK_OpenParen);
|
||||
@@ -207,7 +219,7 @@ null_denotation(Token *token){
|
||||
return ast_expr_cast(token, expr, typespec);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}break;
|
||||
@@ -216,8 +228,8 @@ null_denotation(Token *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{
|
||||
Ast_Expr *result = parse_expr();
|
||||
token_expect(TK_CloseParen);
|
||||
Ast_Expr *result = parse_expr();
|
||||
token_expect(TK_CloseParen);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -226,18 +238,18 @@ null_denotation(Token *token){
|
||||
}
|
||||
|
||||
function S64
|
||||
left_binding_power(Token_Kind kind){
|
||||
left_binding_power(Token_Kind kind){
|
||||
switch(kind){
|
||||
case TK_Sub: case TK_Add: return 1;
|
||||
case TK_Mul: case TK_Div: return 2;
|
||||
case TK_Sub: case TK_Add: return 1;
|
||||
case TK_Mul: case TK_Div: return 2;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function S64
|
||||
postfix_binding_power(Token_Kind kind){
|
||||
postfix_binding_power(Token_Kind 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;
|
||||
}
|
||||
}
|
||||
@@ -259,11 +271,11 @@ parse_expr(S64 rbp){
|
||||
Ast_Expr *left = null_denotation(token);
|
||||
for(;;){
|
||||
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();
|
||||
if(token->kind == TK_OpenBracket){
|
||||
Ast_Expr *index = parse_expr();
|
||||
Ast_Expr *index = parse_expr();
|
||||
left = ast_expr_index(token, left, index);
|
||||
token_expect(TK_CloseBracket);
|
||||
}
|
||||
@@ -273,13 +285,13 @@ parse_expr(S64 rbp){
|
||||
left = ast_expr_unary(token, token->kind, left);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else if(rbp < left_binding_power(token->kind)){
|
||||
token = token_next();
|
||||
left = left_denotation(token, left);
|
||||
}
|
||||
else break;
|
||||
|
||||
|
||||
}
|
||||
return left;
|
||||
}
|
||||
@@ -312,11 +324,11 @@ expr_eval(Ast_Expr *expr){
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_PARSER() \
|
||||
Scratch scratch(thread_ctx.scratch);\
|
||||
Parse_Ctx ctx = {}; \
|
||||
ctx.init(scratch, scratch); \
|
||||
pctx = &ctx
|
||||
#define TEST_PARSER() \
|
||||
Scratch scratch(thread_ctx.scratch); \
|
||||
Parse_Ctx ctx = {}; \
|
||||
ctx.init(scratch, scratch); \
|
||||
pctx = &ctx
|
||||
|
||||
function void
|
||||
test_parse_expr(){
|
||||
@@ -329,8 +341,8 @@ test_parse_expr(){
|
||||
exprs.add({"4+5*2"_s, 4+5*2});
|
||||
exprs.add({"4*5+5"_s, 4*5+5});
|
||||
exprs.add({"4+5+5+3"_s, 4+5+5+3});
|
||||
|
||||
Iter(exprs){
|
||||
|
||||
For(exprs){
|
||||
lex_restream(&ctx, it->str, "test_expr"_s);
|
||||
Ast_Expr *result = parse_expr();
|
||||
S64 val = expr_eval(result);
|
||||
@@ -341,12 +353,11 @@ test_parse_expr(){
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parsing declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// [10]*int - Array of 10 pointers to ints
|
||||
function Ast_Typespec *
|
||||
parse_typespec_recurse(){
|
||||
Token *token = token_get();
|
||||
if(token_match(TK_BitXor)){
|
||||
if(token_match(TK_Pointer)){
|
||||
Ast_Typespec *result = parse_typespec_recurse();
|
||||
result = ast_typespec_pointer(token, result);
|
||||
return result;
|
||||
@@ -395,20 +406,20 @@ parse_decl(){
|
||||
Ast_Expr *expr = parse_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_Expr *expr = 0;
|
||||
if(!token_is(TK_Assign)) typespec = parse_typespec();
|
||||
if(token_match(TK_Assign)) expr = parse_expr();
|
||||
if(!expr && !typespec) parsing_error(name, "invalid declaration, no type or value");
|
||||
|
||||
|
||||
result = ast_decl_var(name, typespec, name->intern_val, expr);
|
||||
}
|
||||
else{
|
||||
Token *token = token_get();
|
||||
parsing_error(token, "Unexpected token: [%s] when parsing a declaration", token_kind_string(token->kind).str);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
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
|
||||
|
||||
enum Sym_Kind{
|
||||
@@ -12,7 +12,7 @@ struct Sym{
|
||||
Intern_String name;
|
||||
Sym_Kind kind;
|
||||
Ast_Decl *decl;
|
||||
Type *type;
|
||||
Ast_Resolved_Type *type;
|
||||
union{
|
||||
S64 int_val;
|
||||
Intern_String intern_val;
|
||||
@@ -20,7 +20,7 @@ struct Sym{
|
||||
};
|
||||
|
||||
struct Operand{
|
||||
Type *type;
|
||||
Ast_Resolved_Type *type;
|
||||
bool is_const;
|
||||
union {
|
||||
S64 int_val;
|
||||
@@ -33,9 +33,9 @@ sym_insert(Sym *sym){
|
||||
U64 hash = hash_string(sym->name.s);
|
||||
Sym *is_sym = (Sym *)map_get_u64(&pctx->global_syms, hash);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ sym_get(Intern_String name){
|
||||
}
|
||||
|
||||
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);
|
||||
result->name = name;
|
||||
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 = {};
|
||||
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);
|
||||
Sym *sym = sym_new(SYM_Type, string, type, &empty_decl);
|
||||
sym_insert(sym);
|
||||
@@ -69,33 +69,31 @@ sym_insert_builtins(){
|
||||
sym_insert_builtin_type("bool"_s, type_bool);
|
||||
sym_insert_builtin_type("int"_s, type_int);
|
||||
sym_insert_builtin_type("String"_s, type_string);
|
||||
|
||||
|
||||
{
|
||||
Intern_String string = intern_string(&pctx->interns, "true"_s);
|
||||
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
|
||||
sym_insert(sym);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
Intern_String string = intern_string(&pctx->interns, "false"_s);
|
||||
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
|
||||
sym_insert(sym);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
Intern_String string = intern_string(&pctx->interns, "null"_s);
|
||||
Sym *sym = sym_new(SYM_Const, string, type_null, &empty_decl);
|
||||
sym_insert(sym);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function Operand eval_expr(Ast_Expr *ast, Type *compound_required_type = 0);
|
||||
function Type *
|
||||
function Operand eval_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0);
|
||||
function Ast_Resolved_Type *
|
||||
eval_typespec(Ast_Typespec *ast){
|
||||
if(!ast) return 0;
|
||||
|
||||
|
||||
switch(ast->kind){
|
||||
Ast_Begin(AST_TYPESPEC_IDENT, Ast_Typespec){
|
||||
Sym *type_sym = sym_get(node->name);
|
||||
@@ -105,34 +103,36 @@ eval_typespec(Ast_Typespec *ast){
|
||||
if(type_sym->kind != SYM_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_Begin(AST_TYPESPEC_LAMBDA, Ast_Typespec){
|
||||
Scratch scratch;
|
||||
Type *ret = eval_typespec(node->lambda->ret);
|
||||
Array<Type *> params = {scratch};
|
||||
Ast_Resolved_Type *ret = eval_typespec(node->lambda->ret);
|
||||
Array<Ast_Resolved_Type *> params = {scratch};
|
||||
For(node->lambda->params) params.add(eval_typespec(it[0]->lambda_param.typespec));
|
||||
Type *result = type_lambda(ret, params);
|
||||
return result;
|
||||
node->resolved_type = type_lambda(ret, params);
|
||||
return node->resolved_type;
|
||||
Ast_End();
|
||||
}
|
||||
|
||||
|
||||
Ast_Begin(AST_TYPESPEC_POINTER, Ast_Typespec){
|
||||
Type *type = eval_typespec(node->base);
|
||||
Type *result = type_pointer(type);
|
||||
return result;
|
||||
Ast_Resolved_Type *type = eval_typespec(node->base);
|
||||
node->resolved_type = type_pointer(type);
|
||||
return node->resolved_type;
|
||||
Ast_End();
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
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");
|
||||
Type *result = type_array(type, expr.int_val);
|
||||
return result;
|
||||
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]);
|
||||
node->resolved_type = type_array(type, expr.int_val);
|
||||
return node->resolved_type;
|
||||
Ast_End();
|
||||
}
|
||||
invalid_default_case;
|
||||
@@ -140,43 +140,94 @@ eval_typespec(Ast_Typespec *ast){
|
||||
return 0;
|
||||
}
|
||||
|
||||
function Type *
|
||||
resolve_type_pair(Token *pos, Type *a, Type *b){
|
||||
Type *result = 0;
|
||||
function Ast_Resolved_Type *
|
||||
resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){
|
||||
Ast_Resolved_Type *result = 0;
|
||||
if(!a && b) result = b;
|
||||
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
|
||||
if(b->kind == TYPE_Null) result = a;
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
if(result->kind == TYPE_Null) parsing_error(pos, "Couldn't infer type of null value");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function Operand
|
||||
eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
||||
function Operand
|
||||
eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type){
|
||||
switch(ast->kind){
|
||||
Ast_Begin(AST_INT, Ast_Expr){
|
||||
Operand result = {type_int, true, {.int_val=(S64)node->int_val}};
|
||||
return result;
|
||||
Ast_End();
|
||||
}
|
||||
|
||||
|
||||
Ast_Begin(AST_STR, Ast_Expr){
|
||||
Operand result = {type_string, true, {.intern_val = node->intern_val}};
|
||||
return result;
|
||||
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){
|
||||
Type *type = eval_typespec(ast_typespec_lambda(0, node));
|
||||
Ast_Resolved_Type *type = eval_typespec(ast_typespec_lambda(0, node));
|
||||
return {type, true};
|
||||
Ast_End();
|
||||
}
|
||||
|
||||
|
||||
Ast_Begin(AST_INDEX, Ast_Expr){
|
||||
Operand left = eval_expr(node->index.expr);
|
||||
Operand index = eval_expr(node->index.index);
|
||||
@@ -186,81 +237,71 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
||||
return result;
|
||||
Ast_End();
|
||||
}
|
||||
|
||||
|
||||
Ast_Begin(AST_COMPOUND, Ast_Expr){
|
||||
Type *type = eval_typespec(node->compound.typespec);
|
||||
Type *variable_type = exp_compound_type;
|
||||
Ast_Resolved_Type *type = eval_typespec(node->compound.typespec);
|
||||
Ast_Resolved_Type *variable_type = expected_type;
|
||||
if(!type && variable_type) type = variable_type;
|
||||
else if(!variable_type && 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(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){
|
||||
assert(it[0]->kind == AST_COMPOUND_ITEM);
|
||||
Ast_Expr *i = (Ast_Expr *)it[0];
|
||||
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){
|
||||
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.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");
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
else parsing_error(node->pos, "Invalid compound expression type");
|
||||
|
||||
|
||||
Operand result = {type, false};
|
||||
return result;
|
||||
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){
|
||||
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;
|
||||
|
||||
|
||||
else if(expr.type == type_int && type == type_bool){
|
||||
expr.type = type_bool;
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
||||
else if(expr.type == type_bool && type == type_int){
|
||||
expr.type = type_int;
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
||||
else if(expr.type == type_null){
|
||||
expr.type = type;
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
||||
else parsing_error(node->pos, "Failed to cast, incompatible types");
|
||||
|
||||
|
||||
Ast_End();
|
||||
}
|
||||
|
||||
|
||||
Ast_Begin(AST_UNARY, Ast_Expr){
|
||||
Operand value = eval_expr(node->unary.expr);
|
||||
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");
|
||||
Operand result = {value.type->base};
|
||||
return result;
|
||||
@@ -271,10 +312,10 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
||||
}break;
|
||||
invalid_default_case; return {};
|
||||
}
|
||||
|
||||
|
||||
Ast_End();
|
||||
}
|
||||
|
||||
|
||||
Ast_Begin(AST_BINARY, Ast_Expr){
|
||||
Operand left = eval_expr(ast->binary.left);
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
Ast_End();
|
||||
}
|
||||
|
||||
|
||||
invalid_default_case;
|
||||
}
|
||||
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
function void
|
||||
eval_decl(Ast *ast){
|
||||
switch(ast->kind){
|
||||
|
||||
|
||||
Ast_Begin(AST_PACKAGE, Ast_Package){
|
||||
For(node->decls) eval_decl(*it);
|
||||
Ast_End();
|
||||
}
|
||||
|
||||
|
||||
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{};
|
||||
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_insert(sym);
|
||||
Ast_End();
|
||||
}
|
||||
|
||||
|
||||
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");
|
||||
Operand expr = eval_expr(node->var.expr);
|
||||
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");
|
||||
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);
|
||||
if(resolved_type == type_int) sym->int_val = expr.int_val;
|
||||
else if(resolved_type == type_string) sym->intern_val = expr.intern_val;
|
||||
sym_insert(sym);
|
||||
Ast_End();
|
||||
}
|
||||
|
||||
|
||||
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_Null,
|
||||
TYPE_Int,
|
||||
@@ -8,41 +8,41 @@ enum Type_Kind{
|
||||
TYPE_Void,
|
||||
TYPE_Pointer,
|
||||
TYPE_Array,
|
||||
TYPE_Func,
|
||||
TYPE_Lambda,
|
||||
TYPE_Struct,
|
||||
TYPE_Union,
|
||||
TYPE_Enum,
|
||||
};
|
||||
|
||||
const char *type_names[] = {
|
||||
"[Invalid Type]",
|
||||
"[TYPE_Null]",
|
||||
"[TYPE_Int]",
|
||||
"[TYPE_Bool]",
|
||||
"[TYPE_Unsigned]",
|
||||
"[TYPE_String]",
|
||||
"[TYPE_Void]",
|
||||
"[TYPE_Pointer]",
|
||||
"[TYPE_Array]",
|
||||
"[TYPE_Func]",
|
||||
"[TYPE_Struct]",
|
||||
"[TYPE_Union]",
|
||||
"[TYPE_Enum]",
|
||||
"[Invalid Ast_Resolved_Type]",
|
||||
"[Null]",
|
||||
"[Int]",
|
||||
"[Bool]",
|
||||
"[Unsigned]",
|
||||
"[String]",
|
||||
"[Void]",
|
||||
"[Pointer]",
|
||||
"[Array]",
|
||||
"[Lambda]",
|
||||
"[Struct]",
|
||||
"[Union]",
|
||||
"[Enum]",
|
||||
};
|
||||
|
||||
struct Type{
|
||||
Type_Kind kind;
|
||||
struct Ast_Resolved_Type{
|
||||
Ast_Resolved_Type_Kind kind;
|
||||
SizeU size;
|
||||
SizeU align;
|
||||
union{
|
||||
Type *base;
|
||||
Ast_Resolved_Type *base;
|
||||
struct{
|
||||
Type *base;
|
||||
Ast_Resolved_Type *base;
|
||||
SizeU size;
|
||||
}arr;
|
||||
struct{
|
||||
Type *ret;
|
||||
Array<Type*> args;
|
||||
Ast_Resolved_Type *ret;
|
||||
Array<Ast_Resolved_Type*> args;
|
||||
}func;
|
||||
};
|
||||
};
|
||||
@@ -50,39 +50,39 @@ struct Type{
|
||||
const SizeU pointer_size = sizeof(SizeU);
|
||||
const SizeU pointer_align = __alignof(SizeU);
|
||||
|
||||
global Type type__null = {TYPE_Null};
|
||||
global Type type__void = {TYPE_Void};
|
||||
global Type type__int = {TYPE_Int, sizeof(int), __alignof(int)};
|
||||
global Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)};
|
||||
global Type type__string = {TYPE_String, sizeof(String), __alignof(String)};
|
||||
global Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)};
|
||||
global Ast_Resolved_Type type__null = {TYPE_Null};
|
||||
global Ast_Resolved_Type type__void = {TYPE_Void};
|
||||
global Ast_Resolved_Type type__int = {TYPE_Int, sizeof(int), __alignof(int)};
|
||||
global Ast_Resolved_Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)};
|
||||
global Ast_Resolved_Type type__string = {TYPE_String, sizeof(String), __alignof(String)};
|
||||
global Ast_Resolved_Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)};
|
||||
|
||||
global Type *type_void = &type__void;
|
||||
global Type *type_int = &type__int;
|
||||
global Type *type_unsigned = &type__unsigned;
|
||||
global Type *type_string = &type__string;
|
||||
global Type *type_bool = &type__bool;
|
||||
global Type *type_null = &type__null;
|
||||
global Ast_Resolved_Type *type_void = &type__void;
|
||||
global Ast_Resolved_Type *type_int = &type__int;
|
||||
global Ast_Resolved_Type *type_unsigned = &type__unsigned;
|
||||
global Ast_Resolved_Type *type_string = &type__string;
|
||||
global Ast_Resolved_Type *type_bool = &type__bool;
|
||||
global Ast_Resolved_Type *type_null = &type__null;
|
||||
|
||||
function Type *
|
||||
type_new(Allocator *allocator, Type_Kind kind, SizeU size, SizeU align){
|
||||
Type *result = exp_alloc_type(allocator, Type);
|
||||
function Ast_Resolved_Type *
|
||||
type_new(Allocator *allocator, Ast_Resolved_Type_Kind kind, SizeU size, SizeU align){
|
||||
Ast_Resolved_Type *result = exp_alloc_type(allocator, Ast_Resolved_Type);
|
||||
result->kind = kind;
|
||||
result->size = size;
|
||||
result->align = align;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Type *
|
||||
type_copy(Allocator *a, Type *type){
|
||||
Type *result = exp_alloc_type(a, Type);
|
||||
memory_copy(result, type, sizeof(Type));
|
||||
function Ast_Resolved_Type *
|
||||
type_copy(Allocator *a, Ast_Resolved_Type *type){
|
||||
Ast_Resolved_Type *result = exp_alloc_type(a, Ast_Resolved_Type);
|
||||
memory_copy(result, type, sizeof(Ast_Resolved_Type));
|
||||
return result;
|
||||
}
|
||||
|
||||
function Type *
|
||||
type_pointer(Type *base){
|
||||
Type *result = (Type *)map_get(&pctx->type_map, (void *)base);
|
||||
function Ast_Resolved_Type *
|
||||
type_pointer(Ast_Resolved_Type *base){
|
||||
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, (void *)base);
|
||||
if(!result){
|
||||
result = type_new(pctx->perm, TYPE_Pointer, pointer_size, pointer_align);
|
||||
result->base = base;
|
||||
@@ -92,17 +92,17 @@ type_pointer(Type *base){
|
||||
return result;
|
||||
}
|
||||
|
||||
function Type *
|
||||
type_array(Type *base, SizeU size){
|
||||
function Ast_Resolved_Type *
|
||||
type_array(Ast_Resolved_Type *base, SizeU 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){
|
||||
assert(result->kind == TYPE_Array);
|
||||
assert(result->arr.size == size);
|
||||
assert(result->arr.base == base);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
result = type_new(pctx->perm, TYPE_Array, pointer_size, pointer_align);
|
||||
result->arr.base = base;
|
||||
result->arr.size = size;
|
||||
@@ -110,24 +110,24 @@ type_array(Type *base, SizeU size){
|
||||
return result;
|
||||
}
|
||||
|
||||
function Type *
|
||||
type_lambda(Type *ret, Array<Type *> args){
|
||||
function Ast_Resolved_Type *
|
||||
type_lambda(Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
|
||||
U64 hash = hash_ptr(ret);
|
||||
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){
|
||||
assert(result->kind == TYPE_Func);
|
||||
assert(result->kind == TYPE_Lambda);
|
||||
assert(result->func.ret == ret);
|
||||
assert(result->func.args.len == args.len);
|
||||
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.args = args.tight_copy(pctx->perm);
|
||||
map_insert_u64(&pctx->type_map, hash, result);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -137,34 +137,34 @@ test_types(){
|
||||
Parse_Ctx ctx = {};
|
||||
ctx.init(scratch, scratch);
|
||||
pctx = &ctx;
|
||||
|
||||
Type *array_type1 = type_array(type_int, 32);
|
||||
Type *array_type2 = type_array(type_int, 32);
|
||||
Type *array_type3 = type_array(type_int, 48);
|
||||
|
||||
Ast_Resolved_Type *array_type1 = type_array(type_int, 32);
|
||||
Ast_Resolved_Type *array_type2 = type_array(type_int, 32);
|
||||
Ast_Resolved_Type *array_type3 = type_array(type_int, 48);
|
||||
assert(array_type1 == array_type2);
|
||||
assert(array_type2 != array_type3);
|
||||
Type *pointer_type1 = type_pointer(type_int);
|
||||
Type *pointer_type2 = type_pointer(type_int);
|
||||
Ast_Resolved_Type *pointer_type1 = type_pointer(type_int);
|
||||
Ast_Resolved_Type *pointer_type2 = type_pointer(type_int);
|
||||
assert(pointer_type2 == pointer_type1);
|
||||
Type *pointer_type3 = type_pointer(pointer_type1);
|
||||
Type *pointer_type4 = type_pointer(pointer_type2);
|
||||
Ast_Resolved_Type *pointer_type3 = type_pointer(pointer_type1);
|
||||
Ast_Resolved_Type *pointer_type4 = type_pointer(pointer_type2);
|
||||
assert(pointer_type3 != pointer_type1);
|
||||
assert(pointer_type3 == pointer_type4);
|
||||
|
||||
Array<Type*> types = {scratch};
|
||||
|
||||
Array<Ast_Resolved_Type*> types = {scratch};
|
||||
types.add(type_array(type_int, 32));
|
||||
Type *func_type1 = type_lambda(types[0], types);
|
||||
Type *func_type2 = type_lambda(types[0], types);
|
||||
Ast_Resolved_Type *func_type1 = type_lambda(types[0], types);
|
||||
Ast_Resolved_Type *func_type2 = type_lambda(types[0], types);
|
||||
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_int);
|
||||
}
|
||||
types.add(type_int);
|
||||
Type *func_type3 = type_lambda(types[0], types);
|
||||
Type *func_type4 = type_lambda(types[0], types2);
|
||||
Ast_Resolved_Type *func_type3 = type_lambda(types[0], types);
|
||||
Ast_Resolved_Type *func_type4 = type_lambda(types[0], types2);
|
||||
assert(func_type1 != func_type3);
|
||||
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{
|
||||
Token_Array tokens;
|
||||
Arena *arena;
|
||||
|
||||
|
||||
Parser_Error *first_error;
|
||||
Parser_Error *last_error;
|
||||
}Parser;
|
||||
@@ -38,36 +38,36 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
|
||||
va_copy(args2, args1);
|
||||
string.len = vsnprintf(0, 0, str, args2);
|
||||
va_end(args2);
|
||||
|
||||
|
||||
string.str = arena_push_size(p->arena, string.len + 1);
|
||||
vsnprintf((char*)string.str, string.len + 1, str, args1);
|
||||
va_end(args1);
|
||||
}
|
||||
|
||||
|
||||
// @Note(Krzosa): Print nice error message
|
||||
printf("\nError: %s", string.str);
|
||||
if(token){
|
||||
printf(" %s:%d\n", token->file.str, (S32)token->line);
|
||||
|
||||
|
||||
// @Note(Krzosa): Print error line
|
||||
{
|
||||
int i = 0;
|
||||
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
|
||||
printf("%.*s\n", i, token->line_begin);
|
||||
|
||||
|
||||
// @Note(Krzosa): Print error marker
|
||||
int token_i = token->str - token->line_begin;
|
||||
for(int i = 0; i < token_i-2; i++) printf(" ");
|
||||
printf("^^^^^^\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Parser_Error *error = arena_push_struct(p->arena, Parser_Error);
|
||||
error->message = string;
|
||||
error->next = 0;
|
||||
error->token = token;
|
||||
SLLQueuePush(p->first_error, p->last_error, error);
|
||||
|
||||
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
@@ -162,15 +162,15 @@ compare = == | != | >= | > | <= | <
|
||||
logical = [&|^] | && | ||
|
||||
unary = [&*-!~+] | ++ | --
|
||||
|
||||
atom_expr = Int
|
||||
| Float
|
||||
| String
|
||||
atom_expr = Int
|
||||
| Float
|
||||
| String
|
||||
| Identifier
|
||||
| 'cast' '(' typespec ',' expr ')'
|
||||
| 'size_type' '(' typespec ')'
|
||||
| 'size_expr' '(' expr ')'
|
||||
| '{' compound_expr '}'
|
||||
| '(' expr ')'
|
||||
| '(' expr ')'
|
||||
| '(' ':' typespec ')' '{' compound_expr '}'
|
||||
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
|
||||
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");
|
||||
}
|
||||
result = expr_compound_named(p->arena, token, expr->intern_val, parse_expr(p));
|
||||
|
||||
|
||||
}
|
||||
else{
|
||||
result = expr_compound_default(p->arena, token, expr);
|
||||
@@ -251,7 +251,7 @@ parse_expr_atom(Parser *p){
|
||||
else if(token_is(p, TK_OpenBrace)){
|
||||
result = parse_expr_compound(p, 0);
|
||||
}
|
||||
|
||||
|
||||
else if(token_match(p, TK_OpenParen)){
|
||||
if(token_match(p, TK_Colon)){
|
||||
Typespec *typespec = parse_typespec(p);
|
||||
@@ -343,7 +343,7 @@ parse_expr_postfix(Parser *p){
|
||||
function B32
|
||||
token_is_unary(Parser *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_Decrement
|
||||
|| token->kind == TK_Sub
|
||||
@@ -462,15 +462,15 @@ parse_expr(Parser *p){
|
||||
// Type specifier parsing
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
base_type = NAME
|
||||
base_type = NAME
|
||||
| '(' type_list? ')' type?
|
||||
|
||||
type = ('*' | '[' expr ']')* base_type
|
||||
|
||||
Examples:
|
||||
Examples:
|
||||
[32]*U32 - Array of 32 pointers to U32
|
||||
**CustomDataType - Pointer to pointer of CustomDataType
|
||||
(*U32, S64) **S64 - Function pointer
|
||||
(*U32, S64) **S64 - Function pointer
|
||||
(CoolType: optional, S32) - Implicit void return value
|
||||
|
||||
*/
|
||||
@@ -490,9 +490,9 @@ parse_optional_type(Parser *p, Intern_String type){
|
||||
function Typespec *
|
||||
parse_typespec_function(Parser *p, Token *token){
|
||||
Typespec *result = typespec_function(p->arena, token, 0);
|
||||
if(!token_is(p, TK_CloseParen))
|
||||
if(!token_is(p, TK_CloseParen))
|
||||
for(;;) {
|
||||
|
||||
|
||||
// Optional name
|
||||
Token *name = 0;
|
||||
if((token = token_is(p, TK_Identifier))){
|
||||
@@ -502,21 +502,21 @@ parse_typespec_function(Parser *p, Token *token){
|
||||
name = token;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Parse type
|
||||
Typespec *arg = parse_typespec(p);
|
||||
if(name)
|
||||
if(name)
|
||||
arg = typespec_named_argument(p->arena, name, arg, name->intern_val);
|
||||
typespec_function_push(result, arg);
|
||||
|
||||
|
||||
if(!token_match(p, TK_Comma)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
token_expect(p, TK_CloseParen);
|
||||
|
||||
|
||||
result->func.ret = parse_optional_type(p, intern_void);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -578,7 +578,7 @@ name::const = 4254;
|
||||
// }
|
||||
// }
|
||||
*/
|
||||
function void
|
||||
function void
|
||||
parse_note_list(Parser *p, AST_Parent *parent) {
|
||||
if(token_match(p, TK_OpenParen)) {
|
||||
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) {
|
||||
while(token_match(p, TK_At)) {
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(result){
|
||||
result->notes = note;
|
||||
ast_push_last(parent, result);
|
||||
@@ -806,7 +806,7 @@ parse_decl(Parser *p, AST_Parent *parent){
|
||||
function AST *parse_stmt(Parser *p);
|
||||
/*
|
||||
stmt_list = '{' stmt* '}'
|
||||
stmt =
|
||||
stmt =
|
||||
| stmt_list
|
||||
| 'return' expr ';'
|
||||
| 'if' expr stmt_list
|
||||
@@ -969,11 +969,11 @@ parse_stmt(Parser *p){
|
||||
result = parse_simple_stmt(p);
|
||||
token_expect(p, TK_Semicolon);
|
||||
}
|
||||
|
||||
|
||||
if(result){
|
||||
result->notes = notes;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1017,7 +1017,7 @@ eval_expr(Expr *expr){
|
||||
case TK_LesserThen: return left < right; break;
|
||||
case TK_BitAnd: 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_Or: return left || right; break;
|
||||
case TK_LeftShift: return left << right; break;
|
||||
@@ -1083,11 +1083,11 @@ parse_test_expr(){
|
||||
" 1>5 ? 1 : 2 "
|
||||
" !!!!!1 "
|
||||
" ~~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 *p = &parser;
|
||||
|
||||
|
||||
S64 t = 5;
|
||||
S64 test_val[] = {
|
||||
(32+52-242*2/424%5-23),
|
||||
@@ -1106,7 +1106,7 @@ parse_test_expr(){
|
||||
S64 val = eval_expr(expr);
|
||||
assert(val == test_val[i]);
|
||||
}
|
||||
|
||||
|
||||
String exprs[] = {
|
||||
lit("cast([12](thing: U32, qwe: *U32): [32]Result, (123+234))"),
|
||||
lit("cast((thing: U32, qwe: *U32), (123+234))"),
|
||||
@@ -1123,7 +1123,7 @@ parse_test_expr(){
|
||||
expr_print(expr);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
arena_end_scratch();
|
||||
}
|
||||
|
||||
@@ -1131,7 +1131,7 @@ function void
|
||||
parse_test_decls(){
|
||||
Arena *scratch = arena_begin_scratch();
|
||||
Parser p = parser_make(scratch);
|
||||
|
||||
|
||||
String decls[] = {
|
||||
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;} }"),
|
||||
@@ -1156,7 +1156,7 @@ parse_test_from_file(){
|
||||
arena_end_scratch();
|
||||
}
|
||||
|
||||
function void
|
||||
function void
|
||||
parse_test_stmt(){
|
||||
Arena *scratch = arena_begin_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
|
||||
name: String
|
||||
|
||||
@@ -12,7 +10,7 @@ compound_of_struct: 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)
|
||||
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
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Function types
|
||||
//-----------------------------------------------------------------------------
|
||||
test_function :: (thing: int): ^int
|
||||
function_type: (thing: int): ^int = test_function
|
||||
const_function_alias :: test_function
|
||||
null_function: (t: int): ^int = null
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Booleans
|
||||
//-----------------------------------------------------------------------------
|
||||
boolean: bool = true
|
||||
value_of_bool: int = cast(boolean: int)
|
||||
base := null
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Nulls
|
||||
//-----------------------------------------------------------------------------
|
||||
int_null: int = null
|
||||
str_null: String = null
|
||||
bool_null: bool = null
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compound expressions
|
||||
//-----------------------------------------------------------------------------
|
||||
array1: [4]int = {1,2,3,4}
|
||||
array1: [4]int = {1,2,3,4}
|
||||
array2: [32]int = {1,2,3,4}
|
||||
array3: [32]int = {
|
||||
[0] = 0,
|
||||
array3: [32]int = {
|
||||
[0] = null,
|
||||
[1] = 1,
|
||||
[31] = 31,
|
||||
}
|
||||
@@ -61,8 +71,8 @@ implicit_str :: "Hello world"
|
||||
//-----------------------------------------------------------------------------
|
||||
// Pointers
|
||||
//-----------------------------------------------------------------------------
|
||||
pointer: ^int = cast(null: ^int)
|
||||
pointer2: ^int = null
|
||||
pointer1: ^int = null
|
||||
pointer2: ^int = pointer1
|
||||
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