Generating valid c code, more work on null values
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
clang main.cpp -I.. -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib
|
pushd %~dp0
|
||||||
|
clang main.cpp -O0 -I.. -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib
|
||||||
|
popd
|
||||||
|
|||||||
232
cgenerate.cpp
Normal file
232
cgenerate.cpp
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
|
||||||
|
#define genln(...) do{printf("\n"); gen_indent(); gen(__VA_ARGS__); }while(0)
|
||||||
|
#define gen(...) printf(__VA_ARGS__)
|
||||||
|
global S32 global_indent;
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_indent(){
|
||||||
|
for(S32 i = 0; i < global_indent; i++) gen(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo: Gen complicated decl
|
||||||
|
//array 10 ( pointer (pointer array 5 int a))
|
||||||
|
// int (*(*(a[5])))[10]
|
||||||
|
//
|
||||||
|
// 1 Get to the bottom
|
||||||
|
// 2 Add variable name
|
||||||
|
// 3 Going backwards add arrays and pointers in parens
|
||||||
|
// 4 Add type name on the left side
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_simple_decl_prefix(Ast_Resolved_Type *ast){
|
||||||
|
switch(ast->kind){
|
||||||
|
case TYPE_Int: gen("int "); break;
|
||||||
|
case TYPE_Bool: gen("bool "); break;
|
||||||
|
case TYPE_Unsigned: gen("unsigned "); break;
|
||||||
|
case TYPE_String: gen("String "); break;
|
||||||
|
case TYPE_Void: gen("void "); break;
|
||||||
|
case TYPE_Pointer:{gen_simple_decl_prefix(ast->base); gen("*");} break;
|
||||||
|
case TYPE_Array: gen_simple_decl_prefix(ast->base); break;
|
||||||
|
case TYPE_Lambda:break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_simple_decl_postfix(Ast_Resolved_Type *ast){
|
||||||
|
switch(ast->kind){
|
||||||
|
case TYPE_Int: break;
|
||||||
|
case TYPE_Bool: break;
|
||||||
|
case TYPE_Unsigned: break;
|
||||||
|
case TYPE_String: break;
|
||||||
|
case TYPE_Void: break;
|
||||||
|
case TYPE_Pointer: gen_simple_decl_postfix(ast->base); break;
|
||||||
|
case TYPE_Array: gen("[%d]", (int)ast->arr.size); gen_simple_decl_postfix(ast->arr.base); break;
|
||||||
|
case TYPE_Lambda:break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){
|
||||||
|
if(ast->kind == TYPE_Lambda) {
|
||||||
|
gen_simple_decl_prefix(ast->func.ret);
|
||||||
|
gen("(*%s)(", name.str);
|
||||||
|
For(ast->func.args){
|
||||||
|
gen_simple_decl_prefix(it[0]);
|
||||||
|
if(it != ast->func.args.end() - 1) gen(", ");
|
||||||
|
}
|
||||||
|
gen(")");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
gen_simple_decl_prefix(ast);
|
||||||
|
if(name.len) {
|
||||||
|
gen("%s", name.str);
|
||||||
|
gen_simple_decl_postfix(ast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_expr(Ast_Expr *ast){
|
||||||
|
switch(ast->kind){
|
||||||
|
Ast_Begin(AST_IDENT, Ast_Expr){
|
||||||
|
gen("%s", node->intern_val.str);
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_INT, Ast_Expr){
|
||||||
|
gen("%lld", node->int_val);
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_STR, Ast_Expr){
|
||||||
|
gen("LIT(\"%s\")", node->intern_val.str);
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_INDEX, Ast_Expr){
|
||||||
|
gen_expr(node->index.expr);
|
||||||
|
gen("[");
|
||||||
|
gen_expr(node->index.index);
|
||||||
|
gen("]");
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_UNARY, Ast_Expr){
|
||||||
|
switch(node->unary.op){
|
||||||
|
case TK_Pointer: {
|
||||||
|
gen("(*");
|
||||||
|
gen_expr(node->unary.expr);
|
||||||
|
gen(")");
|
||||||
|
} break;
|
||||||
|
case TK_Dereference: {
|
||||||
|
gen("(&");
|
||||||
|
gen_expr(node->unary.expr);
|
||||||
|
gen(")");
|
||||||
|
} break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_CAST, Ast_Expr){
|
||||||
|
gen("(");
|
||||||
|
gen("(");
|
||||||
|
gen_simple_decl(node->cast.typespec->resolved_type, {});
|
||||||
|
gen(")");
|
||||||
|
gen_expr(node->cast.expr);
|
||||||
|
gen(")");
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_COMPOUND, Ast_Expr){
|
||||||
|
gen("(");
|
||||||
|
gen_simple_decl(node->compound.type, {});
|
||||||
|
gen(")");
|
||||||
|
|
||||||
|
gen("{");
|
||||||
|
For(node->compound.exprs){
|
||||||
|
auto comp = it[0]->compound_item;
|
||||||
|
if(comp.name){
|
||||||
|
gen("[");
|
||||||
|
gen_expr(comp.name);
|
||||||
|
gen("] = ");
|
||||||
|
}
|
||||||
|
if(comp.index){
|
||||||
|
gen("[");
|
||||||
|
gen_expr(comp.index);
|
||||||
|
gen("] = ");
|
||||||
|
}
|
||||||
|
assert(comp.item);
|
||||||
|
gen_expr(comp.item);
|
||||||
|
|
||||||
|
if(!node->compound.exprs.is_last(it)) gen(", ");
|
||||||
|
}
|
||||||
|
gen("}");
|
||||||
|
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
gen_ast(Ast *ast){
|
||||||
|
switch(ast->kind){
|
||||||
|
|
||||||
|
Ast_Begin(AST_PACKAGE, Ast_Package){
|
||||||
|
For(node->decls) gen_ast(*it);
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_VAR, Ast_Decl){
|
||||||
|
genln("");
|
||||||
|
Sym *sym = sym_get(node->name);
|
||||||
|
gen_simple_decl(sym->type, node->name);
|
||||||
|
if(node->var.expr){
|
||||||
|
gen(" = ");
|
||||||
|
gen_expr(node->var.expr);
|
||||||
|
}
|
||||||
|
gen(";");
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_CONST, Ast_Decl){
|
||||||
|
Sym *sym = sym_get(node->name);
|
||||||
|
|
||||||
|
if(sym->type->kind == TYPE_Lambda){
|
||||||
|
if(node->var.expr->kind == AST_LAMBDA){
|
||||||
|
Ast_Lambda *lambda = (Ast_Lambda *)node->var.expr;
|
||||||
|
genln("");
|
||||||
|
gen_simple_decl(lambda->ret->resolved_type, node->name);
|
||||||
|
gen("(");
|
||||||
|
For(lambda->params){
|
||||||
|
assert(it[0]->kind == AST_LAMBDA_PARAM);
|
||||||
|
gen_simple_decl(it[0]->lambda_param.typespec->resolved_type, it[0]->lambda_param.name);
|
||||||
|
if(it != (lambda->params.end() - 1)) gen(", ");
|
||||||
|
}
|
||||||
|
gen(")");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
genln("");
|
||||||
|
gen_simple_decl(sym->type, node->name);
|
||||||
|
gen(" = ");
|
||||||
|
gen_expr(node->var.expr);
|
||||||
|
gen(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(sym->type == type_int){
|
||||||
|
genln("enum { %s = %lld };", node->name.str, sym->int_val);
|
||||||
|
}
|
||||||
|
else if(sym->type == type_string){
|
||||||
|
genln("String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
parsing_error(node->pos, "Unhandled type of constant expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
test_gen(){
|
||||||
|
TEST_PARSER();
|
||||||
|
String filename = "test3.kl"_s;
|
||||||
|
String file_content = os_read_file(scratch, filename);
|
||||||
|
lex_restream(&ctx, file_content, filename);
|
||||||
|
Ast_Package *result = parse_file();
|
||||||
|
sym_insert_builtins();
|
||||||
|
eval_decl(result);
|
||||||
|
gen(R"==(
|
||||||
|
#define null_pointer 0
|
||||||
|
#define null_lambda 0
|
||||||
|
)==");
|
||||||
|
gen_ast(result);
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
66
generate.c
66
generate.c
@@ -1,66 +0,0 @@
|
|||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include "lang.h"
|
|
||||||
#include "os.h"
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
#include "common.c"
|
|
||||||
#include "memory.c"
|
|
||||||
#include "scratch.c"
|
|
||||||
#include "os_win32.c"
|
|
||||||
|
|
||||||
#include "new_lex.c"
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// String replacing util
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
typedef struct String_Map String_Map;
|
|
||||||
struct String_Map{
|
|
||||||
String replace;
|
|
||||||
String with;
|
|
||||||
};
|
|
||||||
|
|
||||||
function void
|
|
||||||
output_template(FILE *f, String filename, String_Map *map, SizeU map_cap){
|
|
||||||
Arena *scratch = arena_begin_scratch();
|
|
||||||
String file = os_read_file(scratch, filename);
|
|
||||||
Token_Array array = lex_stream(scratch, file, filename);
|
|
||||||
for(Token *t = token_array_iter_begin(&array); t->kind != TK_End; t = token_array_iter_next(&array)){
|
|
||||||
String string = t->string;
|
|
||||||
for(SizeU i = 0; i < map_cap; i++){
|
|
||||||
if(string_compare(string, map[i].replace)){
|
|
||||||
string = map[i].with;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(f, "%.*s", (int)string.len, string.str);
|
|
||||||
if(t->kind == TK_OpenBrace) fprintf(f, "\n");
|
|
||||||
if(t->kind == TK_CloseBrace && token_array_iter_peek(&array, 0)->kind != TK_Semicolon) fprintf(f, "\n");
|
|
||||||
if(t->kind == TK_Semicolon) fprintf(f, "\n");
|
|
||||||
if(t->kind == TK_Keyword) fprintf(f, " ");
|
|
||||||
if(t[0].kind == TK_Identifier && token_array_iter_peek(&array, 0)->kind == TK_Identifier) fprintf(f, " ");
|
|
||||||
token_array_iter_peek(&array, 1);
|
|
||||||
}
|
|
||||||
arena_end_scratch();
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(){
|
|
||||||
|
|
||||||
FILE *f = fopen("generated.c", "w");
|
|
||||||
assert(f);
|
|
||||||
String_Map map[] = {
|
|
||||||
{lit("Type"), lit("Decl")},
|
|
||||||
{lit("first"), lit("list_decl.first")},
|
|
||||||
{lit("last"), lit("list_decl.last")},
|
|
||||||
{lit("remove"), lit("decl_list_remove")},
|
|
||||||
{lit("push_front"), lit("decl_dll_list_push_front")},
|
|
||||||
{lit("push"), lit("decl_dll_list_push")},
|
|
||||||
};
|
|
||||||
output_template(f, lit("dllqueue.c"), map, buff_cap(map));
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
33
ideas.cpp
33
ideas.cpp
@@ -1,33 +0,0 @@
|
|||||||
New_Data_Type::typedef int;
|
|
||||||
CONST_VAL::const 324;
|
|
||||||
|
|
||||||
Ideas::enum{
|
|
||||||
One,
|
|
||||||
Two,
|
|
||||||
Three
|
|
||||||
}
|
|
||||||
|
|
||||||
Data::struct{
|
|
||||||
first: int;
|
|
||||||
second: int;
|
|
||||||
idea: Ideas;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function_call::(first_param: Data*, second_param: int[32]){
|
|
||||||
first_param.first = 10;
|
|
||||||
first_param.second = 10;
|
|
||||||
first_param.idea = Ideas.One;
|
|
||||||
p:= first_param;
|
|
||||||
|
|
||||||
for i in 0...32 {
|
|
||||||
second_param[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 32; i++ {
|
|
||||||
second_param[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
6
lex.c
6
lex.c
@@ -86,7 +86,7 @@ typedef enum Token_Kind{
|
|||||||
|
|
||||||
TK_BitAnd,
|
TK_BitAnd,
|
||||||
TK_BitOr,
|
TK_BitOr,
|
||||||
TK_BitXor,
|
TK_Pointer,
|
||||||
TK_And,
|
TK_And,
|
||||||
TK_Or,
|
TK_Or,
|
||||||
TK_FirstLogical = TK_BitAnd,
|
TK_FirstLogical = TK_BitAnd,
|
||||||
@@ -324,7 +324,7 @@ lex__stream(Token_Array *array, Lex_Stream *s){
|
|||||||
case ';': t.kind = TK_Semicolon; break;
|
case ';': t.kind = TK_Semicolon; break;
|
||||||
case '#': t.kind = TK_Pound; break;
|
case '#': t.kind = TK_Pound; break;
|
||||||
CASE2('!', TK_Not, TK_NotEquals);
|
CASE2('!', TK_Not, TK_NotEquals);
|
||||||
CASE2('^', TK_BitXor, TK_XorAssign);
|
CASE2('^', TK_Pointer, TK_XorAssign);
|
||||||
CASE2('=', TK_Assign, TK_Equals);
|
CASE2('=', TK_Assign, TK_Equals);
|
||||||
CASE2('*', TK_Mul, TK_MulAssign);
|
CASE2('*', TK_Mul, TK_MulAssign);
|
||||||
CASE2('%', TK_Mod, TK_ModAssign);
|
CASE2('%', TK_Mod, TK_ModAssign);
|
||||||
@@ -584,7 +584,7 @@ global const char *token_kind_string[] = {
|
|||||||
[TK_Mod] = "%",
|
[TK_Mod] = "%",
|
||||||
[TK_BitAnd] = "&",
|
[TK_BitAnd] = "&",
|
||||||
[TK_BitOr] = "|",
|
[TK_BitOr] = "|",
|
||||||
[TK_BitXor] = "^",
|
[TK_Pointer] = "^",
|
||||||
[TK_Neg] = "~",
|
[TK_Neg] = "~",
|
||||||
[TK_Not] = "!",
|
[TK_Not] = "!",
|
||||||
[TK_OpenParen] = "(",
|
[TK_OpenParen] = "(",
|
||||||
|
|||||||
5
main.cpp
5
main.cpp
@@ -5,11 +5,12 @@
|
|||||||
#include "new_parse.cpp"
|
#include "new_parse.cpp"
|
||||||
#include "new_type.cpp"
|
#include "new_type.cpp"
|
||||||
#include "new_resolve.cpp"
|
#include "new_resolve.cpp"
|
||||||
|
#include "cgenerate.cpp"
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
test_os_memory();
|
test_os_memory();
|
||||||
thread_ctx_init();
|
thread_ctx_init();
|
||||||
|
test_gen();
|
||||||
test_unicode();
|
test_unicode();
|
||||||
test_resolve();
|
test_resolve();
|
||||||
test_types();
|
test_types();
|
||||||
@@ -21,5 +22,3 @@ int main(){
|
|||||||
test_intern_table();
|
test_intern_table();
|
||||||
lex_test();
|
lex_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
26
new_ast.cpp
26
new_ast.cpp
@@ -27,6 +27,10 @@ struct Parse_Ctx:Lexer{
|
|||||||
Token empty_token;
|
Token empty_token;
|
||||||
S64 indent;
|
S64 indent;
|
||||||
|
|
||||||
|
Intern_String intern(String string){
|
||||||
|
return intern_string(&interns, string);
|
||||||
|
}
|
||||||
|
|
||||||
void init(Allocator *perm_allocator, Allocator *heap_allocator){
|
void init(Allocator *perm_allocator, Allocator *heap_allocator){
|
||||||
perm = perm_allocator;
|
perm = perm_allocator;
|
||||||
heap = heap_allocator;
|
heap = heap_allocator;
|
||||||
@@ -85,6 +89,7 @@ struct Ast{
|
|||||||
Token *pos;
|
Token *pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Ast_Resolved_Type;
|
||||||
struct Ast_Typespec;
|
struct Ast_Typespec;
|
||||||
struct Ast_Expr:Ast{
|
struct Ast_Expr:Ast{
|
||||||
union{
|
union{
|
||||||
@@ -94,13 +99,13 @@ struct Ast_Expr:Ast{
|
|||||||
Token_Kind op;
|
Token_Kind op;
|
||||||
Ast_Expr *expr;
|
Ast_Expr *expr;
|
||||||
}unary;
|
}unary;
|
||||||
|
|
||||||
struct{
|
struct{
|
||||||
Token_Kind op;
|
Token_Kind op;
|
||||||
Ast_Expr *left;
|
Ast_Expr *left;
|
||||||
Ast_Expr *right;
|
Ast_Expr *right;
|
||||||
} binary;
|
} binary;
|
||||||
struct{
|
struct{
|
||||||
|
Ast_Resolved_Type *type;
|
||||||
Ast_Typespec *typespec;
|
Ast_Typespec *typespec;
|
||||||
Array<Ast_Expr *> exprs;
|
Array<Ast_Expr *> exprs;
|
||||||
}compound;
|
}compound;
|
||||||
@@ -124,12 +129,19 @@ struct Ast_Expr:Ast{
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Ast_Block : Ast {
|
||||||
|
Array<Ast *> stmts;
|
||||||
|
};
|
||||||
|
|
||||||
struct Ast_Lambda : Ast_Expr {
|
struct Ast_Lambda : Ast_Expr {
|
||||||
Array<Ast_Expr *> params;
|
Array<Ast_Expr *> params;
|
||||||
Ast_Typespec *ret;
|
Ast_Typespec *ret;
|
||||||
|
Ast_Block *block;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Ast_Resolved_Type;
|
||||||
struct Ast_Typespec:Ast{
|
struct Ast_Typespec:Ast{
|
||||||
|
Ast_Resolved_Type *resolved_type;
|
||||||
union{
|
union{
|
||||||
Ast_Typespec *base;
|
Ast_Typespec *base;
|
||||||
Intern_String name;
|
Intern_String name;
|
||||||
@@ -148,10 +160,6 @@ struct Ast_Decl:Ast{
|
|||||||
Ast_Typespec *typespec;
|
Ast_Typespec *typespec;
|
||||||
Ast_Expr *expr;
|
Ast_Expr *expr;
|
||||||
}var;
|
}var;
|
||||||
struct{
|
|
||||||
Array<Ast_Decl*> args;
|
|
||||||
Ast_Typespec *ret;
|
|
||||||
}func;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -164,10 +172,10 @@ struct Ast_Package:Ast{
|
|||||||
// AST Constructors beginning with expressions
|
// AST Constructors beginning with expressions
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#define AST_NEW(T,ikind,ipos) \
|
#define AST_NEW(T,ikind,ipos) \
|
||||||
Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \
|
Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T); \
|
||||||
result->kind = ikind; \
|
result->kind = ikind; \
|
||||||
result->pos = ipos; \
|
result->pos = ipos; \
|
||||||
result->id = ++pctx->unique_ids
|
result->id = ++pctx->unique_ids
|
||||||
|
|
||||||
function Ast_Expr *
|
function Ast_Expr *
|
||||||
ast_expr_string(Token *pos, Intern_String string){
|
ast_expr_string(Token *pos, Intern_String string){
|
||||||
|
|||||||
58
new_lex.cpp
58
new_lex.cpp
@@ -26,7 +26,6 @@ enum Token_Kind{
|
|||||||
|
|
||||||
TK_BitAnd,
|
TK_BitAnd,
|
||||||
TK_BitOr,
|
TK_BitOr,
|
||||||
TK_BitXor,
|
|
||||||
TK_And,
|
TK_And,
|
||||||
TK_Or,
|
TK_Or,
|
||||||
TK_FirstLogical = TK_BitAnd,
|
TK_FirstLogical = TK_BitAnd,
|
||||||
@@ -83,7 +82,7 @@ enum Token_Kind{
|
|||||||
TK_Integer,
|
TK_Integer,
|
||||||
TK_Keyword,
|
TK_Keyword,
|
||||||
|
|
||||||
TK_Pointer = TK_BitXor,
|
TK_Pointer,
|
||||||
TK_Dereference,
|
TK_Dereference,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -172,7 +171,7 @@ lex_set_len(Lex_Stream *s, Token *token){
|
|||||||
function void
|
function void
|
||||||
lex_set_keywords(Lexer *lexer, Array<String> keywords){
|
lex_set_keywords(Lexer *lexer, Array<String> keywords){
|
||||||
Intern_String keyword = {};
|
Intern_String keyword = {};
|
||||||
Iter(keywords){
|
For(keywords){
|
||||||
keyword = intern_string(&lexer->interns, *it);
|
keyword = intern_string(&lexer->interns, *it);
|
||||||
if(it == keywords.begin())
|
if(it == keywords.begin())
|
||||||
lexer->interns.first_keyword = keyword.str;
|
lexer->interns.first_keyword = keyword.str;
|
||||||
@@ -241,27 +240,27 @@ lex_parse_string(Lex_Stream *s, Token *t, U8 c){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CASE2(op, OpName, Assign) \
|
#define CASE2(op, OpName, Assign) \
|
||||||
case op: \
|
case op: \
|
||||||
if (lexc(s) == '=') { \
|
if (lexc(s) == '=') { \
|
||||||
lex_advance(s); \
|
lex_advance(s); \
|
||||||
t.kind = Assign; \
|
t.kind = Assign; \
|
||||||
} else { \
|
} else { \
|
||||||
t.kind = OpName; \
|
t.kind = OpName; \
|
||||||
} \
|
} \
|
||||||
break
|
break
|
||||||
#define CASE3(op, OpName, Assign, Incr) \
|
#define CASE3(op, OpName, Assign, Incr) \
|
||||||
case op: \
|
case op: \
|
||||||
if (lexc(s) == '=') { \
|
if (lexc(s) == '=') { \
|
||||||
lex_advance(s); \
|
lex_advance(s); \
|
||||||
t.kind = Assign; \
|
t.kind = Assign; \
|
||||||
} else if (lexc(s) == op) { \
|
} else if (lexc(s) == op) { \
|
||||||
lex_advance(s); \
|
lex_advance(s); \
|
||||||
t.kind = Incr; \
|
t.kind = Incr; \
|
||||||
} else { \
|
} else { \
|
||||||
t.kind = OpName; \
|
t.kind = OpName; \
|
||||||
} \
|
} \
|
||||||
break
|
break
|
||||||
|
|
||||||
function void
|
function void
|
||||||
lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
||||||
@@ -287,8 +286,8 @@ lex__stream(Intern_Table *table, Array<Token> *array, Lex_Stream *s){
|
|||||||
case '~': t.kind = TK_Neg; break;
|
case '~': t.kind = TK_Neg; break;
|
||||||
case '?': t.kind = TK_Question; break;
|
case '?': t.kind = TK_Question; break;
|
||||||
case '#': t.kind = TK_Pound; break;
|
case '#': t.kind = TK_Pound; break;
|
||||||
|
case '^': t.kind = TK_Pointer; break;
|
||||||
CASE2('!', TK_Not, TK_NotEquals);
|
CASE2('!', TK_Not, TK_NotEquals);
|
||||||
CASE2('^', TK_BitXor, TK_XorAssign);
|
|
||||||
CASE2('=', TK_Assign, TK_Equals);
|
CASE2('=', TK_Assign, TK_Equals);
|
||||||
CASE2('*', TK_Mul, TK_MulAssign);
|
CASE2('*', TK_Mul, TK_MulAssign);
|
||||||
CASE2('%', TK_Mod, TK_ModAssign);
|
CASE2('%', TK_Mod, TK_ModAssign);
|
||||||
@@ -510,7 +509,12 @@ lex_make(Allocator *token_string_arena, Allocator *map_allocator){
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
lex_restream(Lexer *lexer, String istream, String file){
|
lex_restream(Lexer *lexer, String istream, String file){
|
||||||
lexer->stream = {istream, 0, istream.str, file, 0};
|
lexer->stream = {};
|
||||||
|
lexer->stream.stream = istream;
|
||||||
|
lexer->stream.line_begin = istream.str;
|
||||||
|
lexer->stream.file = file;
|
||||||
|
|
||||||
|
|
||||||
lexer->tokens.clear();
|
lexer->tokens.clear();
|
||||||
lexer->token_iter = 0;
|
lexer->token_iter = 0;
|
||||||
lex__stream(&lexer->interns, &lexer->tokens, &lexer->stream);
|
lex__stream(&lexer->interns, &lexer->tokens, &lexer->stream);
|
||||||
@@ -587,7 +591,7 @@ token_kind_string(Token_Kind kind){
|
|||||||
case TK_Mod: return "%"_s;
|
case TK_Mod: return "%"_s;
|
||||||
case TK_BitAnd: return "&"_s;
|
case TK_BitAnd: return "&"_s;
|
||||||
case TK_BitOr: return "|"_s;
|
case TK_BitOr: return "|"_s;
|
||||||
case TK_BitXor: return "^"_s;
|
case TK_Pointer: return "^"_s;
|
||||||
case TK_Neg: return "~"_s;
|
case TK_Neg: return "~"_s;
|
||||||
case TK_Not: return "!"_s;
|
case TK_Not: return "!"_s;
|
||||||
case TK_OpenParen: return "("_s;
|
case TK_OpenParen: return "("_s;
|
||||||
|
|||||||
@@ -165,9 +165,19 @@ parse_optional_type(){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
function Ast_Block *
|
||||||
|
parse_block(){
|
||||||
|
Ast_Block *result = 0;
|
||||||
|
if(token_match(TK_NewScope)){
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
function Ast_Lambda *
|
function Ast_Lambda *
|
||||||
parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typespec is not used currently
|
parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typespec is not used currently
|
||||||
// @Todo(Krzosa): Combine this with typespec function parsing
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast_Expr *> params = {scratch};
|
Array<Ast_Expr *> params = {scratch};
|
||||||
// @Note(Krzosa): No need to guard against "()"
|
// @Note(Krzosa): No need to guard against "()"
|
||||||
@@ -186,6 +196,8 @@ parse_lambda(Token *token, B32 is_typespec = false){ // @Todo(Krzosa): is_typesp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
token_expect(TK_CloseParen);
|
token_expect(TK_CloseParen);
|
||||||
|
|
||||||
|
//Ast_Block *block = parse_block();
|
||||||
Ast_Lambda *result = ast_lambda(token, params, parse_optional_type());
|
Ast_Lambda *result = ast_lambda(token, params, parse_optional_type());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -196,7 +208,7 @@ null_denotation(Token *token){
|
|||||||
case TK_StringLit : return ast_expr_string(token, token->intern_val);
|
case TK_StringLit : return ast_expr_string(token, token->intern_val);
|
||||||
case TK_Identifier: return ast_expr_identifier(token, token->intern_val);
|
case TK_Identifier: return ast_expr_identifier(token, token->intern_val);
|
||||||
case TK_Integer : return ast_expr_integer(token, token->int_val);
|
case TK_Integer : return ast_expr_integer(token, token->int_val);
|
||||||
case TK_BitXor : return ast_expr_unary(token, TK_Dereference, parse_expr());
|
case TK_Pointer : return ast_expr_unary(token, TK_Dereference, parse_expr());
|
||||||
case TK_Keyword: {
|
case TK_Keyword: {
|
||||||
if(token->intern_val == keyword_cast){
|
if(token->intern_val == keyword_cast){
|
||||||
token_expect(TK_OpenParen);
|
token_expect(TK_OpenParen);
|
||||||
@@ -237,7 +249,7 @@ left_binding_power(Token_Kind kind){
|
|||||||
function S64
|
function S64
|
||||||
postfix_binding_power(Token_Kind kind){
|
postfix_binding_power(Token_Kind kind){
|
||||||
switch(kind){
|
switch(kind){
|
||||||
case TK_Increment: case TK_Decrement: case TK_BitXor: case TK_OpenBracket: return 1;
|
case TK_Increment: case TK_Decrement: case TK_Pointer: case TK_OpenBracket: return 1;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,7 +272,7 @@ parse_expr(S64 rbp){
|
|||||||
for(;;){
|
for(;;){
|
||||||
token = token_get();
|
token = token_get();
|
||||||
|
|
||||||
if((rbp == 0) && (token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_BitXor || token->kind == TK_OpenBracket)){
|
if((rbp == 0) && (token->kind == TK_Increment || token->kind == TK_Decrement || token->kind == TK_Pointer || token->kind == TK_OpenBracket)){
|
||||||
token_next();
|
token_next();
|
||||||
if(token->kind == TK_OpenBracket){
|
if(token->kind == TK_OpenBracket){
|
||||||
Ast_Expr *index = parse_expr();
|
Ast_Expr *index = parse_expr();
|
||||||
@@ -312,11 +324,11 @@ expr_eval(Ast_Expr *expr){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_PARSER() \
|
#define TEST_PARSER() \
|
||||||
Scratch scratch(thread_ctx.scratch);\
|
Scratch scratch(thread_ctx.scratch); \
|
||||||
Parse_Ctx ctx = {}; \
|
Parse_Ctx ctx = {}; \
|
||||||
ctx.init(scratch, scratch); \
|
ctx.init(scratch, scratch); \
|
||||||
pctx = &ctx
|
pctx = &ctx
|
||||||
|
|
||||||
function void
|
function void
|
||||||
test_parse_expr(){
|
test_parse_expr(){
|
||||||
@@ -330,7 +342,7 @@ test_parse_expr(){
|
|||||||
exprs.add({"4*5+5"_s, 4*5+5});
|
exprs.add({"4*5+5"_s, 4*5+5});
|
||||||
exprs.add({"4+5+5+3"_s, 4+5+5+3});
|
exprs.add({"4+5+5+3"_s, 4+5+5+3});
|
||||||
|
|
||||||
Iter(exprs){
|
For(exprs){
|
||||||
lex_restream(&ctx, it->str, "test_expr"_s);
|
lex_restream(&ctx, it->str, "test_expr"_s);
|
||||||
Ast_Expr *result = parse_expr();
|
Ast_Expr *result = parse_expr();
|
||||||
S64 val = expr_eval(result);
|
S64 val = expr_eval(result);
|
||||||
@@ -341,12 +353,11 @@ test_parse_expr(){
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Parsing declarations
|
// Parsing declarations
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// [10]*int - Array of 10 pointers to ints
|
// [10]*int - Array of 10 pointers to ints
|
||||||
function Ast_Typespec *
|
function Ast_Typespec *
|
||||||
parse_typespec_recurse(){
|
parse_typespec_recurse(){
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
if(token_match(TK_BitXor)){
|
if(token_match(TK_Pointer)){
|
||||||
Ast_Typespec *result = parse_typespec_recurse();
|
Ast_Typespec *result = parse_typespec_recurse();
|
||||||
result = ast_typespec_pointer(token, result);
|
result = ast_typespec_pointer(token, result);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
139
new_resolve.cpp
139
new_resolve.cpp
@@ -12,7 +12,7 @@ struct Sym{
|
|||||||
Intern_String name;
|
Intern_String name;
|
||||||
Sym_Kind kind;
|
Sym_Kind kind;
|
||||||
Ast_Decl *decl;
|
Ast_Decl *decl;
|
||||||
Type *type;
|
Ast_Resolved_Type *type;
|
||||||
union{
|
union{
|
||||||
S64 int_val;
|
S64 int_val;
|
||||||
Intern_String intern_val;
|
Intern_String intern_val;
|
||||||
@@ -20,7 +20,7 @@ struct Sym{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Operand{
|
struct Operand{
|
||||||
Type *type;
|
Ast_Resolved_Type *type;
|
||||||
bool is_const;
|
bool is_const;
|
||||||
union {
|
union {
|
||||||
S64 int_val;
|
S64 int_val;
|
||||||
@@ -46,7 +46,7 @@ sym_get(Intern_String name){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Sym *
|
function Sym *
|
||||||
sym_new(Sym_Kind kind, Intern_String name, Type *type, Ast_Decl *decl){
|
sym_new(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Ast_Decl *decl){
|
||||||
Sym *result = exp_alloc_type(pctx->perm, Sym);
|
Sym *result = exp_alloc_type(pctx->perm, Sym);
|
||||||
result->name = name;
|
result->name = name;
|
||||||
result->kind = kind;
|
result->kind = kind;
|
||||||
@@ -57,7 +57,7 @@ sym_new(Sym_Kind kind, Intern_String name, Type *type, Ast_Decl *decl){
|
|||||||
|
|
||||||
global Ast_Decl empty_decl = {};
|
global Ast_Decl empty_decl = {};
|
||||||
function void
|
function void
|
||||||
sym_insert_builtin_type(String name, Type *type){
|
sym_insert_builtin_type(String name, Ast_Resolved_Type *type){
|
||||||
Intern_String string = intern_string(&pctx->interns, name);
|
Intern_String string = intern_string(&pctx->interns, name);
|
||||||
Sym *sym = sym_new(SYM_Type, string, type, &empty_decl);
|
Sym *sym = sym_new(SYM_Type, string, type, &empty_decl);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
@@ -87,12 +87,10 @@ sym_insert_builtins(){
|
|||||||
Sym *sym = sym_new(SYM_Const, string, type_null, &empty_decl);
|
Sym *sym = sym_new(SYM_Const, string, type_null, &empty_decl);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Operand eval_expr(Ast_Expr *ast, Type *compound_required_type = 0);
|
function Operand eval_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0);
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
eval_typespec(Ast_Typespec *ast){
|
eval_typespec(Ast_Typespec *ast){
|
||||||
if(!ast) return 0;
|
if(!ast) return 0;
|
||||||
|
|
||||||
@@ -105,34 +103,36 @@ eval_typespec(Ast_Typespec *ast){
|
|||||||
if(type_sym->kind != SYM_Type){
|
if(type_sym->kind != SYM_Type){
|
||||||
parsing_error(node->pos, "This identifier is not a type");
|
parsing_error(node->pos, "This identifier is not a type");
|
||||||
}
|
}
|
||||||
return type_sym->type;
|
|
||||||
|
node->resolved_type = type_sym->type;
|
||||||
|
return node->resolved_type;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_TYPESPEC_LAMBDA, Ast_Typespec){
|
Ast_Begin(AST_TYPESPEC_LAMBDA, Ast_Typespec){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Type *ret = eval_typespec(node->lambda->ret);
|
Ast_Resolved_Type *ret = eval_typespec(node->lambda->ret);
|
||||||
Array<Type *> params = {scratch};
|
Array<Ast_Resolved_Type *> params = {scratch};
|
||||||
For(node->lambda->params) params.add(eval_typespec(it[0]->lambda_param.typespec));
|
For(node->lambda->params) params.add(eval_typespec(it[0]->lambda_param.typespec));
|
||||||
Type *result = type_lambda(ret, params);
|
node->resolved_type = type_lambda(ret, params);
|
||||||
return result;
|
return node->resolved_type;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_TYPESPEC_POINTER, Ast_Typespec){
|
Ast_Begin(AST_TYPESPEC_POINTER, Ast_Typespec){
|
||||||
Type *type = eval_typespec(node->base);
|
Ast_Resolved_Type *type = eval_typespec(node->base);
|
||||||
Type *result = type_pointer(type);
|
node->resolved_type = type_pointer(type);
|
||||||
return result;
|
return node->resolved_type;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_TYPESPEC_ARRAY, Ast_Typespec){
|
Ast_Begin(AST_TYPESPEC_ARRAY, Ast_Typespec){
|
||||||
Type *type = eval_typespec(node->arr.base);
|
Ast_Resolved_Type *type = eval_typespec(node->arr.base);
|
||||||
Operand expr = eval_expr(node->arr.expr);
|
Operand expr = eval_expr(node->arr.expr);
|
||||||
if(!expr.is_const) parsing_error(node->pos, "Array size is not a constant");
|
if(!expr.is_const) parsing_error(node->pos, "Array size is not a constant");
|
||||||
if(expr.type != type_int) parsing_error(node->pos, "Array size is expected to be of type int");
|
if(expr.type != type_int) parsing_error(node->pos, "Array size is expected to be of type [Int] is instead of type %s", type_names[expr.type->kind]);
|
||||||
Type *result = type_array(type, expr.int_val);
|
node->resolved_type = type_array(type, expr.int_val);
|
||||||
return result;
|
return node->resolved_type;
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
@@ -140,24 +140,26 @@ eval_typespec(Ast_Typespec *ast){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
resolve_type_pair(Token *pos, Type *a, Type *b){
|
resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){
|
||||||
Type *result = 0;
|
Ast_Resolved_Type *result = 0;
|
||||||
if(!a && b) result = b;
|
if(!a && b) result = b;
|
||||||
else if(a && !b) result = a;
|
else if(a && !b) result = a;
|
||||||
else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are null");
|
else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are [Null]");
|
||||||
else{ // a && b
|
else{ // a && b
|
||||||
if(b->kind == TYPE_Null) result = a;
|
if(b->kind == TYPE_Null) result = a;
|
||||||
else if(a->kind == TYPE_Null) result = b;
|
else if(a->kind == TYPE_Null) result = b;
|
||||||
else if(a != b) parsing_error(pos, "Expression and type specification are differing");
|
else if(a != b) parsing_error(pos, "Expression and type specification are differing %s %s", type_names[a->kind], type_names[b->kind]);
|
||||||
else result = a; // Types are the same
|
else result = a; // Types are the same
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(result->kind == TYPE_Null) parsing_error(pos, "Couldn't infer type of null value");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
Ast_Begin(AST_INT, Ast_Expr){
|
Ast_Begin(AST_INT, Ast_Expr){
|
||||||
Operand result = {type_int, true, {.int_val=(S64)node->int_val}};
|
Operand result = {type_int, true, {.int_val=(S64)node->int_val}};
|
||||||
@@ -171,8 +173,57 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
|||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ast_Begin(AST_IDENT, Ast_Expr){
|
||||||
|
Sym *sym = sym_get(node->intern_val);
|
||||||
|
if(!sym){
|
||||||
|
parsing_error(node->pos, "Identifier is undefined");
|
||||||
|
}
|
||||||
|
|
||||||
|
// @note: check if null and rewrite the expression to match the expected type
|
||||||
|
Operand result = {};
|
||||||
|
if(sym->type->kind == TYPE_Null){
|
||||||
|
if(!expected_type) parsing_error(node->pos, "Couldn't infer type of null");
|
||||||
|
result.type = expected_type;
|
||||||
|
result.is_const = true;
|
||||||
|
if(expected_type == type_int){
|
||||||
|
result.int_val = 0;
|
||||||
|
node->kind = AST_INT;
|
||||||
|
node->int_val = 0;
|
||||||
|
}
|
||||||
|
else if(expected_type->kind == TYPE_Pointer){
|
||||||
|
result.int_val = 0;
|
||||||
|
node->kind = AST_IDENT;
|
||||||
|
node->intern_val = pctx->intern("null_pointer"_s);
|
||||||
|
}
|
||||||
|
else if(expected_type->kind == TYPE_Lambda){
|
||||||
|
result.int_val = 0;
|
||||||
|
node->kind = AST_IDENT;
|
||||||
|
node->intern_val = pctx->intern("null_lambda"_s);
|
||||||
|
}
|
||||||
|
else if(expected_type == type_bool){
|
||||||
|
result.int_val = 0;
|
||||||
|
node->kind = AST_IDENT;
|
||||||
|
node->intern_val = pctx->intern("false"_s);
|
||||||
|
}
|
||||||
|
else if(expected_type == type_string){
|
||||||
|
result.intern_val = pctx->intern(""_s);
|
||||||
|
node->kind = AST_STR;
|
||||||
|
node->intern_val = result.intern_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result.type = sym->type;
|
||||||
|
result.is_const = sym->kind == SYM_Const ? true : false;
|
||||||
|
result.int_val = sym->int_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
Ast_End();
|
||||||
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_LAMBDA, Ast_Lambda){
|
Ast_Begin(AST_LAMBDA, Ast_Lambda){
|
||||||
Type *type = eval_typespec(ast_typespec_lambda(0, node));
|
Ast_Resolved_Type *type = eval_typespec(ast_typespec_lambda(0, node));
|
||||||
return {type, true};
|
return {type, true};
|
||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
@@ -188,28 +239,29 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_COMPOUND, Ast_Expr){
|
Ast_Begin(AST_COMPOUND, Ast_Expr){
|
||||||
Type *type = eval_typespec(node->compound.typespec);
|
Ast_Resolved_Type *type = eval_typespec(node->compound.typespec);
|
||||||
Type *variable_type = exp_compound_type;
|
Ast_Resolved_Type *variable_type = expected_type;
|
||||||
if(!type && variable_type) type = variable_type;
|
if(!type && variable_type) type = variable_type;
|
||||||
else if(!variable_type && type);
|
else if(!variable_type && type);
|
||||||
else if(variable_type != type) parsing_error(node->pos, "Variable type different from explicit compound type");
|
else if(variable_type != type) parsing_error(node->pos, "Variable type different from explicit compound type");
|
||||||
|
node->compound.type = type;
|
||||||
|
|
||||||
if(type->kind == TYPE_Array){
|
if(type->kind == TYPE_Array){
|
||||||
if(node->compound.exprs.len > type->arr.size) parsing_error(node->pos, "compound statement has too many items for this type");
|
if(node->compound.exprs.len > type->arr.size) parsing_error(node->pos, "compound statement has too many items for this type");
|
||||||
Type *item_type = type->arr.base;
|
Ast_Resolved_Type *item_type = type->arr.base;
|
||||||
|
|
||||||
For(node->compound.exprs){
|
For(node->compound.exprs){
|
||||||
assert(it[0]->kind == AST_COMPOUND_ITEM);
|
assert(it[0]->kind == AST_COMPOUND_ITEM);
|
||||||
Ast_Expr *i = (Ast_Expr *)it[0];
|
Ast_Expr *i = (Ast_Expr *)it[0];
|
||||||
assert(i->kind == AST_COMPOUND_ITEM);
|
assert(i->kind == AST_COMPOUND_ITEM);
|
||||||
if(i->compound_item.name) parsing_error(i->pos, "Invalid array indexing in compound expression");
|
if(i->compound_item.name) parsing_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]);
|
||||||
if(i->compound_item.index){
|
if(i->compound_item.index){
|
||||||
Operand index_op = eval_expr(i->compound_item.index);
|
Operand index_op = eval_expr(i->compound_item.index);
|
||||||
if(!index_op.is_const) parsing_error(i->pos, "Index in a compound expression is not a constant");
|
if(!index_op.is_const) parsing_error(i->pos, "Index in a compound expression is not a constant");
|
||||||
if(index_op.type != type_int) parsing_error(i->pos, "Index should be of type int");
|
if(index_op.type != type_int) parsing_error(i->pos, "Index should be of type int");
|
||||||
if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
||||||
}
|
}
|
||||||
Operand expr = eval_expr(i->compound_item.item);
|
Operand expr = eval_expr(i->compound_item.item, item_type);
|
||||||
resolve_type_pair(i->pos, expr.type, item_type);
|
resolve_type_pair(i->pos, expr.type, item_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,20 +272,9 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
|||||||
Ast_End();
|
Ast_End();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_IDENT, Ast_Expr){
|
|
||||||
Sym *sym = sym_get(node->intern_val);
|
|
||||||
if(!sym){
|
|
||||||
parsing_error(node->pos, "Identifier is undefined");
|
|
||||||
}
|
|
||||||
|
|
||||||
Operand result = {sym->type, sym->kind == SYM_Const ? true : false, {.int_val = sym->int_val}};
|
|
||||||
return result;
|
|
||||||
Ast_End();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ast_Begin(AST_CAST, Ast_Expr){
|
Ast_Begin(AST_CAST, Ast_Expr){
|
||||||
Operand expr = eval_expr(node->cast.expr);
|
Operand expr = eval_expr(node->cast.expr);
|
||||||
Type *type = eval_typespec(node->cast.typespec);
|
Ast_Resolved_Type *type = eval_typespec(node->cast.typespec);
|
||||||
|
|
||||||
if(type == expr.type) return expr;
|
if(type == expr.type) return expr;
|
||||||
|
|
||||||
@@ -260,7 +301,7 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
|
|||||||
Ast_Begin(AST_UNARY, Ast_Expr){
|
Ast_Begin(AST_UNARY, Ast_Expr){
|
||||||
Operand value = eval_expr(node->unary.expr);
|
Operand value = eval_expr(node->unary.expr);
|
||||||
switch(node->unary.op){
|
switch(node->unary.op){
|
||||||
case TK_BitXor:{
|
case TK_Pointer:{
|
||||||
if(value.type->kind != TYPE_Pointer) parsing_error(node->pos, "Dereferencing a value that is not a pointer");
|
if(value.type->kind != TYPE_Pointer) parsing_error(node->pos, "Dereferencing a value that is not a pointer");
|
||||||
Operand result = {value.type->base};
|
Operand result = {value.type->base};
|
||||||
return result;
|
return result;
|
||||||
@@ -314,9 +355,9 @@ eval_decl(Ast *ast){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_VAR, Ast_Decl){
|
Ast_Begin(AST_VAR, Ast_Decl){
|
||||||
Type *type = eval_typespec(node->var.typespec);
|
Ast_Resolved_Type *type = eval_typespec(node->var.typespec);
|
||||||
Operand expr = node->var.expr ? eval_expr(node->var.expr, type) : Operand{};
|
Operand expr = node->var.expr ? eval_expr(node->var.expr, type) : Operand{};
|
||||||
Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
|
Ast_Resolved_Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
|
||||||
|
|
||||||
Sym *sym = sym_new(SYM_Var, node->name, resolved_type, node);
|
Sym *sym = sym_new(SYM_Var, node->name, resolved_type, node);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
@@ -324,12 +365,12 @@ eval_decl(Ast *ast){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_CONST, Ast_Decl){
|
Ast_Begin(AST_CONST, Ast_Decl){
|
||||||
Type *type = eval_typespec(node->var.typespec);
|
Ast_Resolved_Type *type = eval_typespec(node->var.typespec);
|
||||||
if(type && type->kind == TYPE_Pointer) parsing_error(node->pos, "Const cant be a pointer");
|
if(type && type->kind == TYPE_Pointer) parsing_error(node->pos, "Const cant be a pointer");
|
||||||
Operand expr = eval_expr(node->var.expr);
|
Operand expr = eval_expr(node->var.expr);
|
||||||
if(!expr.type) parsing_error(node->pos, "Constant value without expression");
|
if(!expr.type) parsing_error(node->pos, "Constant value without expression");
|
||||||
if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression");
|
if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression");
|
||||||
Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
|
Ast_Resolved_Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
|
||||||
|
|
||||||
Sym *sym = sym_new(SYM_Const, node->name, resolved_type, node);
|
Sym *sym = sym_new(SYM_Const, node->name, resolved_type, node);
|
||||||
if(resolved_type == type_int) sym->int_val = expr.int_val;
|
if(resolved_type == type_int) sym->int_val = expr.int_val;
|
||||||
|
|||||||
128
new_type.cpp
128
new_type.cpp
@@ -1,4 +1,4 @@
|
|||||||
enum Type_Kind{
|
enum Ast_Resolved_Type_Kind{
|
||||||
TYPE_None,
|
TYPE_None,
|
||||||
TYPE_Null,
|
TYPE_Null,
|
||||||
TYPE_Int,
|
TYPE_Int,
|
||||||
@@ -8,41 +8,41 @@ enum Type_Kind{
|
|||||||
TYPE_Void,
|
TYPE_Void,
|
||||||
TYPE_Pointer,
|
TYPE_Pointer,
|
||||||
TYPE_Array,
|
TYPE_Array,
|
||||||
TYPE_Func,
|
TYPE_Lambda,
|
||||||
TYPE_Struct,
|
TYPE_Struct,
|
||||||
TYPE_Union,
|
TYPE_Union,
|
||||||
TYPE_Enum,
|
TYPE_Enum,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *type_names[] = {
|
const char *type_names[] = {
|
||||||
"[Invalid Type]",
|
"[Invalid Ast_Resolved_Type]",
|
||||||
"[TYPE_Null]",
|
"[Null]",
|
||||||
"[TYPE_Int]",
|
"[Int]",
|
||||||
"[TYPE_Bool]",
|
"[Bool]",
|
||||||
"[TYPE_Unsigned]",
|
"[Unsigned]",
|
||||||
"[TYPE_String]",
|
"[String]",
|
||||||
"[TYPE_Void]",
|
"[Void]",
|
||||||
"[TYPE_Pointer]",
|
"[Pointer]",
|
||||||
"[TYPE_Array]",
|
"[Array]",
|
||||||
"[TYPE_Func]",
|
"[Lambda]",
|
||||||
"[TYPE_Struct]",
|
"[Struct]",
|
||||||
"[TYPE_Union]",
|
"[Union]",
|
||||||
"[TYPE_Enum]",
|
"[Enum]",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Type{
|
struct Ast_Resolved_Type{
|
||||||
Type_Kind kind;
|
Ast_Resolved_Type_Kind kind;
|
||||||
SizeU size;
|
SizeU size;
|
||||||
SizeU align;
|
SizeU align;
|
||||||
union{
|
union{
|
||||||
Type *base;
|
Ast_Resolved_Type *base;
|
||||||
struct{
|
struct{
|
||||||
Type *base;
|
Ast_Resolved_Type *base;
|
||||||
SizeU size;
|
SizeU size;
|
||||||
}arr;
|
}arr;
|
||||||
struct{
|
struct{
|
||||||
Type *ret;
|
Ast_Resolved_Type *ret;
|
||||||
Array<Type*> args;
|
Array<Ast_Resolved_Type*> args;
|
||||||
}func;
|
}func;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -50,39 +50,39 @@ struct Type{
|
|||||||
const SizeU pointer_size = sizeof(SizeU);
|
const SizeU pointer_size = sizeof(SizeU);
|
||||||
const SizeU pointer_align = __alignof(SizeU);
|
const SizeU pointer_align = __alignof(SizeU);
|
||||||
|
|
||||||
global Type type__null = {TYPE_Null};
|
global Ast_Resolved_Type type__null = {TYPE_Null};
|
||||||
global Type type__void = {TYPE_Void};
|
global Ast_Resolved_Type type__void = {TYPE_Void};
|
||||||
global Type type__int = {TYPE_Int, sizeof(int), __alignof(int)};
|
global Ast_Resolved_Type type__int = {TYPE_Int, sizeof(int), __alignof(int)};
|
||||||
global Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)};
|
global Ast_Resolved_Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)};
|
||||||
global Type type__string = {TYPE_String, sizeof(String), __alignof(String)};
|
global Ast_Resolved_Type type__string = {TYPE_String, sizeof(String), __alignof(String)};
|
||||||
global Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)};
|
global Ast_Resolved_Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)};
|
||||||
|
|
||||||
global Type *type_void = &type__void;
|
global Ast_Resolved_Type *type_void = &type__void;
|
||||||
global Type *type_int = &type__int;
|
global Ast_Resolved_Type *type_int = &type__int;
|
||||||
global Type *type_unsigned = &type__unsigned;
|
global Ast_Resolved_Type *type_unsigned = &type__unsigned;
|
||||||
global Type *type_string = &type__string;
|
global Ast_Resolved_Type *type_string = &type__string;
|
||||||
global Type *type_bool = &type__bool;
|
global Ast_Resolved_Type *type_bool = &type__bool;
|
||||||
global Type *type_null = &type__null;
|
global Ast_Resolved_Type *type_null = &type__null;
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
type_new(Allocator *allocator, Type_Kind kind, SizeU size, SizeU align){
|
type_new(Allocator *allocator, Ast_Resolved_Type_Kind kind, SizeU size, SizeU align){
|
||||||
Type *result = exp_alloc_type(allocator, Type);
|
Ast_Resolved_Type *result = exp_alloc_type(allocator, Ast_Resolved_Type);
|
||||||
result->kind = kind;
|
result->kind = kind;
|
||||||
result->size = size;
|
result->size = size;
|
||||||
result->align = align;
|
result->align = align;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
type_copy(Allocator *a, Type *type){
|
type_copy(Allocator *a, Ast_Resolved_Type *type){
|
||||||
Type *result = exp_alloc_type(a, Type);
|
Ast_Resolved_Type *result = exp_alloc_type(a, Ast_Resolved_Type);
|
||||||
memory_copy(result, type, sizeof(Type));
|
memory_copy(result, type, sizeof(Ast_Resolved_Type));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
type_pointer(Type *base){
|
type_pointer(Ast_Resolved_Type *base){
|
||||||
Type *result = (Type *)map_get(&pctx->type_map, (void *)base);
|
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, (void *)base);
|
||||||
if(!result){
|
if(!result){
|
||||||
result = type_new(pctx->perm, TYPE_Pointer, pointer_size, pointer_align);
|
result = type_new(pctx->perm, TYPE_Pointer, pointer_size, pointer_align);
|
||||||
result->base = base;
|
result->base = base;
|
||||||
@@ -92,10 +92,10 @@ type_pointer(Type *base){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
type_array(Type *base, SizeU size){
|
type_array(Ast_Resolved_Type *base, SizeU size){
|
||||||
U64 hash = hash_mix(hash_ptr(base), hash_u64(size));
|
U64 hash = hash_mix(hash_ptr(base), hash_u64(size));
|
||||||
Type *result = (Type *)map_get_u64(&pctx->type_map, hash);
|
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get_u64(&pctx->type_map, hash);
|
||||||
if(result){
|
if(result){
|
||||||
assert(result->kind == TYPE_Array);
|
assert(result->kind == TYPE_Array);
|
||||||
assert(result->arr.size == size);
|
assert(result->arr.size == size);
|
||||||
@@ -110,20 +110,20 @@ type_array(Type *base, SizeU size){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type *
|
function Ast_Resolved_Type *
|
||||||
type_lambda(Type *ret, Array<Type *> args){
|
type_lambda(Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
|
||||||
U64 hash = hash_ptr(ret);
|
U64 hash = hash_ptr(ret);
|
||||||
For(args) hash = hash_mix(hash, hash_ptr(*it));
|
For(args) hash = hash_mix(hash, hash_ptr(*it));
|
||||||
Type *result = (Type *)map_get_u64(&pctx->type_map, hash);
|
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get_u64(&pctx->type_map, hash);
|
||||||
|
|
||||||
if(result){
|
if(result){
|
||||||
assert(result->kind == TYPE_Func);
|
assert(result->kind == TYPE_Lambda);
|
||||||
assert(result->func.ret == ret);
|
assert(result->func.ret == ret);
|
||||||
assert(result->func.args.len == args.len);
|
assert(result->func.args.len == args.len);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = type_new(pctx->perm, TYPE_Func, pointer_size, pointer_align);
|
result = type_new(pctx->perm, TYPE_Lambda, pointer_size, pointer_align);
|
||||||
result->func.ret = ret;
|
result->func.ret = ret;
|
||||||
result->func.args = args.tight_copy(pctx->perm);
|
result->func.args = args.tight_copy(pctx->perm);
|
||||||
map_insert_u64(&pctx->type_map, hash, result);
|
map_insert_u64(&pctx->type_map, hash, result);
|
||||||
@@ -138,33 +138,33 @@ test_types(){
|
|||||||
ctx.init(scratch, scratch);
|
ctx.init(scratch, scratch);
|
||||||
pctx = &ctx;
|
pctx = &ctx;
|
||||||
|
|
||||||
Type *array_type1 = type_array(type_int, 32);
|
Ast_Resolved_Type *array_type1 = type_array(type_int, 32);
|
||||||
Type *array_type2 = type_array(type_int, 32);
|
Ast_Resolved_Type *array_type2 = type_array(type_int, 32);
|
||||||
Type *array_type3 = type_array(type_int, 48);
|
Ast_Resolved_Type *array_type3 = type_array(type_int, 48);
|
||||||
assert(array_type1 == array_type2);
|
assert(array_type1 == array_type2);
|
||||||
assert(array_type2 != array_type3);
|
assert(array_type2 != array_type3);
|
||||||
Type *pointer_type1 = type_pointer(type_int);
|
Ast_Resolved_Type *pointer_type1 = type_pointer(type_int);
|
||||||
Type *pointer_type2 = type_pointer(type_int);
|
Ast_Resolved_Type *pointer_type2 = type_pointer(type_int);
|
||||||
assert(pointer_type2 == pointer_type1);
|
assert(pointer_type2 == pointer_type1);
|
||||||
Type *pointer_type3 = type_pointer(pointer_type1);
|
Ast_Resolved_Type *pointer_type3 = type_pointer(pointer_type1);
|
||||||
Type *pointer_type4 = type_pointer(pointer_type2);
|
Ast_Resolved_Type *pointer_type4 = type_pointer(pointer_type2);
|
||||||
assert(pointer_type3 != pointer_type1);
|
assert(pointer_type3 != pointer_type1);
|
||||||
assert(pointer_type3 == pointer_type4);
|
assert(pointer_type3 == pointer_type4);
|
||||||
|
|
||||||
Array<Type*> types = {scratch};
|
Array<Ast_Resolved_Type*> types = {scratch};
|
||||||
types.add(type_array(type_int, 32));
|
types.add(type_array(type_int, 32));
|
||||||
Type *func_type1 = type_lambda(types[0], types);
|
Ast_Resolved_Type *func_type1 = type_lambda(types[0], types);
|
||||||
Type *func_type2 = type_lambda(types[0], types);
|
Ast_Resolved_Type *func_type2 = type_lambda(types[0], types);
|
||||||
assert(func_type1 == func_type2);
|
assert(func_type1 == func_type2);
|
||||||
|
|
||||||
Array<Type*> types2 = {scratch};
|
Array<Ast_Resolved_Type*> types2 = {scratch};
|
||||||
{
|
{
|
||||||
types2.add(type_array(type_int, 32));
|
types2.add(type_array(type_int, 32));
|
||||||
types2.add(type_int);
|
types2.add(type_int);
|
||||||
}
|
}
|
||||||
types.add(type_int);
|
types.add(type_int);
|
||||||
Type *func_type3 = type_lambda(types[0], types);
|
Ast_Resolved_Type *func_type3 = type_lambda(types[0], types);
|
||||||
Type *func_type4 = type_lambda(types[0], types2);
|
Ast_Resolved_Type *func_type4 = type_lambda(types[0], types2);
|
||||||
assert(func_type1 != func_type3);
|
assert(func_type1 != func_type3);
|
||||||
assert(func_type3 == func_type4);
|
assert(func_type3 == func_type4);
|
||||||
}
|
}
|
||||||
|
|||||||
294
output.cc
294
output.cc
@@ -1,294 +0,0 @@
|
|||||||
(((534>43)?435:42),234,((S64)32),Thing[10][2],Thing((1,2)))
|
|
||||||
(4+(2*53))
|
|
||||||
((4+2)*53)
|
|
||||||
(++5)
|
|
||||||
(--5)
|
|
||||||
(-5)
|
|
||||||
(+5)
|
|
||||||
(sizeof(32)+sizeof(S32*))
|
|
||||||
((S64**)5)
|
|
||||||
(((S64)5)+3)
|
|
||||||
((534>43)?435:42)
|
|
||||||
struct Thing{
|
|
||||||
int test;
|
|
||||||
};
|
|
||||||
|
|
||||||
S32 thing = 100;
|
|
||||||
(thing=(thing+10));
|
|
||||||
(++thing);
|
|
||||||
{
|
|
||||||
S32 thing_scoped = 10;
|
|
||||||
(thing_scoped+=10);
|
|
||||||
}
|
|
||||||
typedef struct OpenGL OpenGL;
|
|
||||||
typedef struct OS_Memory OS_Memory;
|
|
||||||
typedef struct Arena Arena;
|
|
||||||
typedef struct String String;
|
|
||||||
typedef struct Token Token;
|
|
||||||
typedef struct Lex_Stream Lex_Stream;
|
|
||||||
typedef struct Expr Expr;
|
|
||||||
typedef struct AST_Node AST_Node;
|
|
||||||
typedef struct Parser_Error Parser_Error;
|
|
||||||
typedef struct Scope Scope;
|
|
||||||
typedef struct Parser Parser;
|
|
||||||
struct test{
|
|
||||||
struct Array_Block{
|
|
||||||
Array_Block (*next);
|
|
||||||
Based_Type_Represent (data[size]);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Array{
|
|
||||||
Array_Block first;
|
|
||||||
Array_Block (*last);
|
|
||||||
S64 block;
|
|
||||||
S64 len;
|
|
||||||
};
|
|
||||||
|
|
||||||
function Based_Type_Represent array_make(Arena (*arena)){
|
|
||||||
Test_Type thing;
|
|
||||||
Based_Type_Represent result;
|
|
||||||
((result.arena)=arena);
|
|
||||||
((result.last)=(&(result.first)));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
function void array_push(Array (*array), Based_Type_Represent (*item)){
|
|
||||||
if (((array->len)+1)>size){
|
|
||||||
assert((array->len));
|
|
||||||
Array_Block (*block) = ((Thing)arena_push_struct(((array->arena),sizeof(Array_Block))));
|
|
||||||
((array->last)=(((array->last).next)=block));
|
|
||||||
((array->len)=0);
|
|
||||||
((array->block)+=1);
|
|
||||||
}
|
|
||||||
(((array->last).data)[(++(array->len))]=(*item));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OpenGL{
|
|
||||||
void (*glVertexAttribPointer)(GLuint, GLint, GLenumGLenum, GLboolean, GLsizei, GLvoid *);
|
|
||||||
void (*glBindTexture)(GLenum, GLuint);
|
|
||||||
void (*glDrawArrays)(GLenumGLenum, GLint, GLsizei);
|
|
||||||
int (*(test_array[10]));
|
|
||||||
Things (*thing);
|
|
||||||
S64 thing_cap;
|
|
||||||
S64 thing_len;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OS_Memory{
|
|
||||||
void (*data);
|
|
||||||
SizeU commit;
|
|
||||||
SizeU reserve;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Arena{
|
|
||||||
OS_Memory memory;
|
|
||||||
U64 len;
|
|
||||||
U64 alignment;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct String{
|
|
||||||
U8 (*str);
|
|
||||||
S64 len;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef String Intern_String;
|
|
||||||
typedef enum Token_Kind{
|
|
||||||
TK_End,
|
|
||||||
TK_Mul,
|
|
||||||
TK_Div,
|
|
||||||
TK_Add,
|
|
||||||
TK_Sub,
|
|
||||||
TK_Mod,
|
|
||||||
TK_BitAnd,
|
|
||||||
TK_BitOr,
|
|
||||||
TK_BitXor,
|
|
||||||
TK_Neg,
|
|
||||||
TK_Not,
|
|
||||||
TK_OpenParen,
|
|
||||||
TK_CloseParen,
|
|
||||||
TK_OpenBrace,
|
|
||||||
TK_CloseBrace,
|
|
||||||
TK_OpenBracket,
|
|
||||||
TK_CloseBracket,
|
|
||||||
TK_Comma,
|
|
||||||
TK_Pound,
|
|
||||||
TK_Question,
|
|
||||||
TK_ThreeDots,
|
|
||||||
TK_Semicolon,
|
|
||||||
TK_Dot,
|
|
||||||
TK_LesserThen,
|
|
||||||
TK_GreaterThen,
|
|
||||||
TK_Colon,
|
|
||||||
TK_Assign,
|
|
||||||
TK_DivAssign,
|
|
||||||
TK_MulAssign,
|
|
||||||
TK_ModAssign,
|
|
||||||
TK_SubAssign,
|
|
||||||
TK_AddAssign,
|
|
||||||
TK_AndAssign,
|
|
||||||
TK_OrAssign,
|
|
||||||
TK_XorAssign,
|
|
||||||
TK_LeftShiftAssign,
|
|
||||||
TK_RightShiftAssign,
|
|
||||||
TK_DoubleColon,
|
|
||||||
TK_At,
|
|
||||||
TK_Decrement,
|
|
||||||
TK_Increment,
|
|
||||||
TK_PostDecrement,
|
|
||||||
TK_PostIncrement,
|
|
||||||
TK_LesserThenOrEqual,
|
|
||||||
TK_GreaterThenOrEqual,
|
|
||||||
TK_Equals,
|
|
||||||
TK_And,
|
|
||||||
TK_Or,
|
|
||||||
TK_NotEquals,
|
|
||||||
TK_LeftShift,
|
|
||||||
TK_RightShift,
|
|
||||||
TK_Arrow,
|
|
||||||
TK_ExprSizeof,
|
|
||||||
TK_DocComment,
|
|
||||||
TK_Comment,
|
|
||||||
TK_Identifier,
|
|
||||||
TK_StringLit,
|
|
||||||
TK_U8Lit,
|
|
||||||
TK_Character,
|
|
||||||
TK_Error,
|
|
||||||
TK_Float,
|
|
||||||
TK_Int,
|
|
||||||
TK_Keyword,
|
|
||||||
}Token_Kind;
|
|
||||||
|
|
||||||
struct Token{
|
|
||||||
Token_Kind kind;
|
|
||||||
String string;
|
|
||||||
union{
|
|
||||||
S64 integer_val;
|
|
||||||
String error_val;
|
|
||||||
Intern_String intern_val;
|
|
||||||
};
|
|
||||||
String file;
|
|
||||||
S64 line;
|
|
||||||
U8 (*line_begin);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Lex_Stream{
|
|
||||||
U8 (*stream);
|
|
||||||
U8 (*line_begin);
|
|
||||||
String filename;
|
|
||||||
S64 line;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum Expr_Kind{
|
|
||||||
EK_None,
|
|
||||||
EK_Atom,
|
|
||||||
EK_Unary,
|
|
||||||
EK_Binary,
|
|
||||||
EK_Ternary,
|
|
||||||
EK_Cast,
|
|
||||||
EK_List,
|
|
||||||
EK_Call,
|
|
||||||
EK_Index,
|
|
||||||
}Expr_Kind;
|
|
||||||
|
|
||||||
struct Expr{
|
|
||||||
Expr_Kind kind;
|
|
||||||
Token (*token);
|
|
||||||
Expr (*next);
|
|
||||||
union{
|
|
||||||
struct{
|
|
||||||
AST_Node (*type);
|
|
||||||
Expr (*expr);
|
|
||||||
}cast_val;
|
|
||||||
struct{
|
|
||||||
Expr (*first);
|
|
||||||
Expr (*last);
|
|
||||||
}list;
|
|
||||||
struct{
|
|
||||||
Expr (*atom);
|
|
||||||
Expr (*list);
|
|
||||||
}call;
|
|
||||||
struct{
|
|
||||||
Expr (*atom);
|
|
||||||
Expr (*index);
|
|
||||||
}index;
|
|
||||||
struct{
|
|
||||||
Expr (*expr);
|
|
||||||
}unary;
|
|
||||||
struct{
|
|
||||||
Expr (*left);
|
|
||||||
Expr (*right);
|
|
||||||
}binary;
|
|
||||||
struct{
|
|
||||||
Expr (*cond);
|
|
||||||
Expr (*on_true);
|
|
||||||
Expr (*on_false);
|
|
||||||
}ternary;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum AST_Kind{
|
|
||||||
AK_None,
|
|
||||||
AK_BaseType,
|
|
||||||
AK_Typedef,
|
|
||||||
AK_Enum,
|
|
||||||
AK_Struct,
|
|
||||||
AK_Union,
|
|
||||||
AK_Note,
|
|
||||||
AK_List,
|
|
||||||
AK_Pointer,
|
|
||||||
AK_Array,
|
|
||||||
AK_Function,
|
|
||||||
AK_Variable,
|
|
||||||
AK_EnumChild,
|
|
||||||
}AST_Kind;
|
|
||||||
|
|
||||||
struct AST_Node{
|
|
||||||
AST_Kind kind;
|
|
||||||
Token (*pos);
|
|
||||||
Intern_String name;
|
|
||||||
AST_Node (*next);
|
|
||||||
AST_Node (*next_scope);
|
|
||||||
AST_Node (*first_note);
|
|
||||||
AST_Node (*last_note);
|
|
||||||
AST_Node (*first_child);
|
|
||||||
AST_Node (*last_child);
|
|
||||||
union{
|
|
||||||
SizeU base_type_size;
|
|
||||||
AST_Node (*pointer);
|
|
||||||
AST_Node (*typedef_type);
|
|
||||||
AST_Node (*variable_type);
|
|
||||||
AST_Node (*func_return_type);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Parser_Error{
|
|
||||||
Parser_Error (*next);
|
|
||||||
String message;
|
|
||||||
Token (*token);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Scope{
|
|
||||||
Scope (*next);
|
|
||||||
AST_Node (*first);
|
|
||||||
AST_Node (*last);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Parser{
|
|
||||||
Arena main_arena;
|
|
||||||
Arena intern_table_arena;
|
|
||||||
Arena symbol_table_arena;
|
|
||||||
Scope (*scope_free_list);
|
|
||||||
Scope (*scope_stack);
|
|
||||||
Scope (*global_scope);
|
|
||||||
S64 symbols_inserted;
|
|
||||||
S64 symbols_count;
|
|
||||||
AST_Node (*symbols);
|
|
||||||
Intern_String (*interns);
|
|
||||||
S64 interns_in_bytes;
|
|
||||||
S64 interns_inserted;
|
|
||||||
S64 interns_count;
|
|
||||||
U8 (*first_keyword);
|
|
||||||
U8 (*last_keyword);
|
|
||||||
Parser_Error default;
|
|
||||||
Parser_Error error;
|
|
||||||
};
|
|
||||||
|
|
||||||
2
parse.c
2
parse.c
@@ -1017,7 +1017,7 @@ eval_expr(Expr *expr){
|
|||||||
case TK_LesserThen: return left < right; break;
|
case TK_LesserThen: return left < right; break;
|
||||||
case TK_BitAnd: return left & right; break;
|
case TK_BitAnd: return left & right; break;
|
||||||
case TK_BitOr: return left | right; break;
|
case TK_BitOr: return left | right; break;
|
||||||
case TK_BitXor: return left ^ right; break;
|
case TK_Pointer: return left ^ right; break;
|
||||||
case TK_And: return left && right; break;
|
case TK_And: return left && right; break;
|
||||||
case TK_Or: return left || right; break;
|
case TK_Or: return left || right; break;
|
||||||
case TK_LeftShift: return left << right; break;
|
case TK_LeftShift: return left << right; break;
|
||||||
|
|||||||
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;
|
|
||||||
|
|
||||||
28
test3.kl
28
test3.kl
@@ -1,6 +1,4 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Player :: struct
|
Player :: struct
|
||||||
id : int
|
id : int
|
||||||
name: String
|
name: String
|
||||||
@@ -12,7 +10,7 @@ compound_of_struct: Player = {
|
|||||||
|
|
||||||
second_compound_syntax := :Player{...}
|
second_compound_syntax := :Player{...}
|
||||||
|
|
||||||
max :: (a: int, b: int) { if a > b then return a; return b; }
|
max_folding :: (a: int, b: int) { if a > b { return a; } return b; }
|
||||||
|
|
||||||
max :: (a: int, b: int)
|
max :: (a: int, b: int)
|
||||||
if a > b then return a
|
if a > b then return a
|
||||||
@@ -22,22 +20,34 @@ max :: (a: int, b: int)
|
|||||||
{ and } - treated as new line scope and end of new line scope
|
{ and } - treated as new line scope and end of new line scope
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Function types
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
test_function :: (thing: int): ^int
|
test_function :: (thing: int): ^int
|
||||||
|
function_type: (thing: int): ^int = test_function
|
||||||
|
const_function_alias :: test_function
|
||||||
|
null_function: (t: int): ^int = null
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Booleans
|
// Booleans
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
boolean: bool = true
|
boolean: bool = true
|
||||||
value_of_bool: int = cast(boolean: int)
|
value_of_bool: int = cast(boolean: int)
|
||||||
base := null
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Nulls
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int_null: int = null
|
||||||
|
str_null: String = null
|
||||||
|
bool_null: bool = null
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Compound expressions
|
// Compound expressions
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
array1: [4]int = {1,2,3,4}
|
array1: [4]int = {1,2,3,4}
|
||||||
array2: [32]int = {1,2,3,4}
|
array2: [32]int = {1,2,3,4}
|
||||||
array3: [32]int = {
|
array3: [32]int = {
|
||||||
[0] = 0,
|
[0] = null,
|
||||||
[1] = 1,
|
[1] = 1,
|
||||||
[31] = 31,
|
[31] = 31,
|
||||||
}
|
}
|
||||||
@@ -61,8 +71,8 @@ implicit_str :: "Hello world"
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Pointers
|
// Pointers
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
pointer: ^int = cast(null: ^int)
|
pointer1: ^int = null
|
||||||
pointer2: ^int = null
|
pointer2: ^int = pointer1
|
||||||
pointer3: ^^int = null
|
pointer3: ^^int = null
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|||||||
157
type.c
157
type.c
@@ -1,157 +0,0 @@
|
|||||||
typedef struct Type Type;
|
|
||||||
|
|
||||||
typedef enum Type_Kind{
|
|
||||||
TYPE_None,
|
|
||||||
TYPE_Incomplete,
|
|
||||||
TYPE_Int,
|
|
||||||
TYPE_Char,
|
|
||||||
TYPE_Void,
|
|
||||||
TYPE_Pointer,
|
|
||||||
TYPE_Array,
|
|
||||||
TYPE_Func,
|
|
||||||
TYPE_Struct,
|
|
||||||
TYPE_Union,
|
|
||||||
TYPE_Enum,
|
|
||||||
}Type_Kind;
|
|
||||||
|
|
||||||
struct Type{
|
|
||||||
Type_Kind kind;
|
|
||||||
SizeU size;
|
|
||||||
SizeU align;
|
|
||||||
struct{
|
|
||||||
Type *base;
|
|
||||||
}pointer;
|
|
||||||
struct{
|
|
||||||
Type *base;
|
|
||||||
SizeU size;
|
|
||||||
}array;
|
|
||||||
struct{
|
|
||||||
Type **params;
|
|
||||||
S32 count;
|
|
||||||
Type *ret;
|
|
||||||
}func;
|
|
||||||
};
|
|
||||||
|
|
||||||
global Type global_type[] = {
|
|
||||||
{TYPE_Void},
|
|
||||||
{TYPE_Int, sizeof(int), __alignof(int)},
|
|
||||||
{TYPE_Char, sizeof(char), __alignof(char)},
|
|
||||||
};
|
|
||||||
|
|
||||||
const SizeU pointer_size = sizeof(SizeU);
|
|
||||||
const SizeU pointer_align = __alignof(SizeU);
|
|
||||||
|
|
||||||
global Type *type_void = global_type + 0;
|
|
||||||
global Type *type_int = global_type + 1;
|
|
||||||
global Type *type_char = global_type + 2;
|
|
||||||
|
|
||||||
global Map map_pointer_types;
|
|
||||||
global Map map_array_types;
|
|
||||||
global Map map_func_types;
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_new(Arena *arena, Type_Kind kind, SizeU size, SizeU align){
|
|
||||||
Type *result = arena_push_struct(arena, Type);
|
|
||||||
result->kind = kind;
|
|
||||||
result->size = size;
|
|
||||||
result->align = align;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_copy(Arena *arena, Type *type){
|
|
||||||
Type *result = arena_push_struct(arena, Type);
|
|
||||||
memory_copy(result, type, sizeof(Type));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_incomplete(Arena *arena){
|
|
||||||
Type *result = type_new(arena, TYPE_Incomplete, 0, 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_pointer(Arena *arena, Type *base){
|
|
||||||
Type *result = map_get(&map_pointer_types, (void *)base);
|
|
||||||
if(!result){
|
|
||||||
result = type_new(arena, TYPE_Pointer, pointer_size, pointer_align);
|
|
||||||
result->pointer.base = base;
|
|
||||||
map_insert(&map_pointer_types, base, result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_array(Arena *arena, Type *base, SizeU size){
|
|
||||||
U64 hash = hash_mix(hash_ptr(base), hash_u64(size));
|
|
||||||
Type *result = map_get_u64(&map_array_types, hash);
|
|
||||||
if(result){
|
|
||||||
assert(result->array.size == size);
|
|
||||||
assert(result->array.base == base);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = type_new(arena, TYPE_Array, pointer_size, pointer_align);
|
|
||||||
result->array.base = base;
|
|
||||||
result->array.size = size;
|
|
||||||
map_insert_u64(&map_array_types, hash, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Type *
|
|
||||||
type_lambda(Arena *arena, Type *ret, Type **params, S32 count){
|
|
||||||
U64 hash = hash_ptr(ret);
|
|
||||||
for(S32 i = 0; i < count; i++)
|
|
||||||
hash = hash_mix(hash, hash_ptr(params[i]));
|
|
||||||
|
|
||||||
Type *result = map_get_u64(&map_func_types, hash);
|
|
||||||
if(result){
|
|
||||||
assert(result->func.ret == ret);
|
|
||||||
assert(result->func.count == count);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = type_new(arena, TYPE_Func, pointer_size, pointer_align);
|
|
||||||
result->func.ret = ret;
|
|
||||||
result->func.count = count;
|
|
||||||
result->func.params = arena_push_array(arena, Type*, count);
|
|
||||||
memory_copy(result->func.params, params, count);
|
|
||||||
map_insert_u64(&map_func_types, hash, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function void
|
|
||||||
test_types(){
|
|
||||||
Arena *arena = arena_begin_scratch();
|
|
||||||
Type *array_type1 = type_array(arena, type_int, 32);
|
|
||||||
Type *array_type2 = type_array(arena, type_int, 32);
|
|
||||||
Type *array_type3 = type_array(arena, type_int, 48);
|
|
||||||
assert(array_type1 == array_type2);
|
|
||||||
assert(array_type2 != array_type3);
|
|
||||||
Type *pointer_type1 = type_pointer(arena, type_int);
|
|
||||||
Type *pointer_type2 = type_pointer(arena, type_int);
|
|
||||||
assert(pointer_type2 == pointer_type1);
|
|
||||||
Type *pointer_type3 = type_pointer(arena, pointer_type1);
|
|
||||||
Type *pointer_type4 = type_pointer(arena, pointer_type2);
|
|
||||||
assert(pointer_type3 != pointer_type1);
|
|
||||||
assert(pointer_type3 == pointer_type4);
|
|
||||||
|
|
||||||
Type **types = 0;
|
|
||||||
array_push(types, type_array(arena, type_int, 32));
|
|
||||||
Type *func_type1 = type_lambda(arena, types[0], types, array_len(types));
|
|
||||||
Type *func_type2 = type_lambda(arena, types[0], types, array_len(types));
|
|
||||||
assert(func_type1 == func_type2);
|
|
||||||
|
|
||||||
Type **types2 = 0;
|
|
||||||
{
|
|
||||||
array_push(types2, type_array(arena, type_int, 32));
|
|
||||||
array_push(types2, type_int);
|
|
||||||
}
|
|
||||||
array_push(types, type_int);
|
|
||||||
Type *func_type3 = type_lambda(arena, types[0], types, array_len(types));
|
|
||||||
Type *func_type4 = type_lambda(arena, types[0], types2, array_len(types));
|
|
||||||
assert(func_type1 != func_type3);
|
|
||||||
assert(func_type3 == func_type4);
|
|
||||||
|
|
||||||
arena_end_scratch();
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user