Add string accessors, working towards first program

This commit is contained in:
Krzosa Karol
2022-06-03 21:59:51 +02:00
parent 827cad0127
commit 5e798bd179
8 changed files with 191 additions and 115 deletions

View File

@@ -405,7 +405,30 @@ compile_string(String filecontent, String filename = "default_name"_s){
gen(R"==( gen(R"==(
// Generated
#include <stdint.h>
typedef int8_t S8;
typedef int16_t S16;
typedef int32_t S32;
typedef int64_t S64;
typedef uint8_t U8;
typedef uint16_t U16;
typedef uint32_t U32;
typedef uint64_t U64;
typedef S8 B8;
typedef S16 B16;
typedef S32 B32;
typedef S64 B64;
typedef U64 SizeU;
typedef S64 SizeI;
typedef float F32;
typedef double F64;
struct String{
U8 *str;
S64 len;
};
)=="); )==");
F64 resolve_begin = os_time(); F64 resolve_begin = os_time();

View File

@@ -1,16 +0,0 @@
/*
Lex_Stream :: struct
stream: String
offset: Int
lexc :: (s: *Lex_Stream): String // @todo U8 U S
return s.stream + s.offset // s.offset @todo Actual string support
main :: ()
string_to_lex := "Identifier 2425525 Not_Number"
s := Lex_Stream(stream=string_to_lex)
for inf:=0, inf, inf // @todo for
pass
*/

View File

@@ -32,23 +32,26 @@ For now I don't thing it should be overloadable.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@todo @todo
[ ] - Operators: Bit negation, Not [ ] - Converting from U64 token to S64 Atom introduces unnanounced error (negates) - probably need big int
[ ] - Compiling and running a program [ ] - Compiling and running a program
[ ] - Passing down program to compile through command line [ ] - Passing down program to compile through command line
[ ] - More for loop variations [ ] - More for loop variations
[ ] - Fixing access to constants, in C we cant have constants inside of structs / functions so we need to rewrite the tree
[ ] - Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative
[ ] - Write up on order independent declarations [ ] - Write up on order independent declarations
[ ] - Switch [ ] - Switch
[ ] - More basic types
[ ] - Comma notation when declaring variables thing1, thing2: S32
[ ] - Array of inferred size [ ] - Array of inferred size
[ ] - Add single line lambda expressions [ ] - Add single line lambda expressions
[ ] - Ternary operator [ ] - Ternary operator
[ ] - Field access rewrite
[ ] - Constants embeded in structs should be able to refer to other constants in that namespace without prefix [ ] - Constants embeded in structs should be able to refer to other constants in that namespace without prefix
[ ] - Converting from U64 token to S64 Atom introduces unnanounced error (negates) - probably need
[ ] - Order independent constants in structs [ ] - Order independent constants in structs
[ ] - Can you even have recursive lambdas in structs, other recursive stuff [ ] - Fix recursive lambdas in structs
[ ] - Fixing access to functions/structs, in C we cant have functons inside of structs / functions so we need to rewrite the tree
[ ] - Casting to basic types by call S64(x) [ ] - Casting to basic types by call S64(x)
[ ] - Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative
[ ] - Type aliases :: should probably be strictly typed, but assigning constant values should work [ ] - Type aliases :: should probably be strictly typed, but assigning constant values should work
@ideas @ideas
@@ -59,16 +62,19 @@ For now I don't thing it should be overloadable.
@donzo @donzo
[x] - Test new operators, add constant eval for them [x] - Test new operators, add constant eval for them
[x] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression [x] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression
[x] - More basic types
[x] - Add basic support for floats [x] - Add basic support for floats
[x] - Add basic setup for new type system [x] - Add basic setup for new type system
[x] - Access through struct names to constants Arena.CONSTANT [x] - Access through struct names to constants Arena.CONSTANT
[x] - Enums [x] - Enums
[x] - Initial for loop [x] - Initial for loop
[x] - Enum . access to values [x] - Enum . access to values
[x] - Infinite for loop
[x] - in new typesystem: Fix calls, fix all example programs [x] - in new typesystem: Fix calls, fix all example programs
[x] - Fix arithmetic operations in new type system [x] - Fix arithmetic operations in new type system
[x] - Init statements, different kinds [+=] [-=] etc. [x] - Init statements, different kinds [+=] [-=] etc.
[x] - Struct calls [x] - Struct calls
[x] - Operators: Bit negation, Not
[x] - Default values in calls [x] - Default values in calls
[x] - Resolving calls with default values [x] - Resolving calls with default values
[x] - Pass statement [x] - Pass statement
@@ -119,11 +125,11 @@ int main(){
result = compile_file("new_types.kl"_s); result = compile_file("new_types.kl"_s);
printf("%s", result.str); printf("%s", result.str);
// result = compile_file("lexer.kl"_s); result = compile_file("program.kl"_s);
// FILE *f = fopen("program.c", "w"); FILE *f = fopen("program.c", "w");
// assert(f); assert(f);
// fprintf(f, "%.*s", (int)result.len, result.str); fprintf(f, "%.*s", (int)result.len, result.str);
// fclose(f); fclose(f);
__debugbreak(); __debugbreak();
} }

View File

@@ -193,16 +193,21 @@ parse_block(){
} }
else if(token_match_keyword(keyword_for)){ else if(token_match_keyword(keyword_for)){
Ast_Expr *expr_first = parse_expr(); Ast_Expr *init = 0;
Ast_Expr *init = parse_init_stmt(expr_first);
Ast_Expr *cond = 0; Ast_Expr *cond = 0;
Ast_Expr *iter = 0; Ast_Expr *iter = 0;
if(token_match(TK_Comma)){
cond = parse_expr(); if(!token_is(OPEN_SCOPE)){
Ast_Expr *expr_first = parse_expr();
init = parse_init_stmt(expr_first);
if(token_match(TK_Comma)){ if(token_match(TK_Comma)){
iter = parse_expr(); cond = parse_expr();
iter = parse_init_stmt(iter); if(token_match(TK_Comma)){
iter = parse_expr();
iter = parse_init_stmt(iter);
}
} }
} }
@@ -345,7 +350,7 @@ binding_power(Binding binding, Token_Kind kind){
case TK_Mod: case TK_Mod:
return {17,18}; return {17,18};
case TK_Dot: case TK_Dot:
return {20,19}; return {24,23};
default: return {}; default: return {};
} }
Postfix: switch(kind){ Postfix: switch(kind){

View File

@@ -47,11 +47,11 @@ basic_type_assignment :: ()
float_var := float_val float_var := float_val
compounds :: ()
custom_data := Custom_Data(thing = 23)
Custom_Data :: struct Custom_Data :: struct
thing: S32 thing: S32
// constant_proc :: ()
// compounds :: () // constant_proc()
// custom_data := Custom_Data(23)

View File

@@ -1,6 +1,36 @@
//-------------------------------
#define NULL_POINTER 0
#define NULL_LAMBDA 0
//-------------------------------
#include <stdint.h>
typedef int8_t S8;
typedef int16_t S16;
typedef int32_t S32;
typedef int64_t S64;
typedef uint8_t U8;
typedef uint16_t U16;
typedef uint32_t U32;
typedef uint64_t U64;
typedef S8 B8;
typedef S16 B16;
typedef S32 B32;
typedef S64 B64;
typedef U64 SizeU;
typedef S64 SizeI;
typedef float F32;
typedef double F64;
struct String{
U8 *str;
S64 len;
};
struct Lex_Stream{
U8 *stream;
U8 *end;
};
static Void main(){
String string_to_lex = LIT("Identifier 2425525 Not_Number");
for(S64 i = 0;(i<string_to_lex.len);(i+=1)){
(string_to_lex.str[0]=64);
}
}

11
program.kl Normal file
View File

@@ -0,0 +1,11 @@
Lex_Stream :: struct
stream: *U8
end : *U8
main :: ()
string_to_lex := "Identifier 2425525 Not_Number"
for i := 0, i < string_to_lex.len, i+=1
string_to_lex.str[0] = 64

View File

@@ -278,7 +278,7 @@ function void
try_untyping(Operand *op){ try_untyping(Operand *op){
if(!op) return; if(!op) return;
if(is_untyped(op->type)){ if(is_untyped(op->type)){
if(op->type->kind == TYPE_UNTYPED_INT) op->type = type_int; if(op->type->kind == TYPE_UNTYPED_INT) op->type = type_s64;
else if(op->type->kind == TYPE_UNTYPED_BOOL) op->type = type_bool; else if(op->type->kind == TYPE_UNTYPED_BOOL) op->type = type_bool;
else if(op->type->kind == TYPE_UNTYPED_STRING) op->type = type_string; else if(op->type->kind == TYPE_UNTYPED_STRING) op->type = type_string;
else if(op->type->kind == TYPE_UNTYPED_FLOAT) op->type = type_f64; else if(op->type->kind == TYPE_UNTYPED_FLOAT) op->type = type_f64;
@@ -394,11 +394,6 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
BREAK(); BREAK();
} }
CASE(BINARY, Binary){
resolve_expr(node);
BREAK();
}
CASE(PASS, Pass){ CASE(PASS, Pass){
unused(node); unused(node);
BREAK(); BREAK();
@@ -422,7 +417,12 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
BREAK(); BREAK();
} }
invalid_default_case; default:{
if(is_flag_set(ast->flags, AST_EXPR)){
resolve_expr((Ast_Expr *)ast);
}
else invalid_codepath;
}
} }
} }
@@ -486,6 +486,19 @@ resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){
return result; return result;
} }
function Operand
field_access_string(Ast_Expr *right){
if(right->kind == AST_BINARY) invalid_codepath; // @todo entire field access needs a rework
assert(right->kind == AST_IDENT);
auto a = (Ast_Atom *)right;
if(a->intern_val == pctx->intern("len"_s)){
return operand_lvalue(type_s64);
} else if(a->intern_val == pctx->intern("str"_s)){
return operand_lvalue(type_pointer(type_u8));
} else invalid_return;
}
function Operand function Operand
resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_resolve){ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_resolve){
if(!ast) return {}; // @todo: add option for better error prevention if(!ast) return {}; // @todo: add option for better error prevention
@@ -533,7 +546,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
CASE(INDEX, Index){ CASE(INDEX, Index){
Operand left = resolve_expr(node->expr); Operand left = resolve_expr(node->expr);
Operand index = resolve_expr(node->index); Operand index = resolve_expr(node->index);
if(left.type->kind != TYPE_ARRAY) parsing_error(node->pos, "Indexing variable that is not an array, it's of type %s instead", docname(left.type)); if(left.type->kind != TYPE_ARRAY && left.type->kind != TYPE_POINTER) parsing_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %s instead", docname(left.type));
if(!is_int(index.type)) type_error(node->pos, type_int, index.type,"Trying to index the array with invalid type, expected int"); if(!is_int(index.type)) type_error(node->pos, type_int, index.type,"Trying to index the array with invalid type, expected int");
return operand_lvalue(left.type->arr.base); return operand_lvalue(left.type->arr.base);
BREAK(); BREAK();
@@ -695,10 +708,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
else{ parsing_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; } else{ parsing_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; }
}break; }break;
case TK_Dereference:{return operand_lvalue(type_pointer(value.type));}break; case TK_Dereference:{return operand_lvalue(type_pointer(value.type));}break;
case TK_Neg: case TK_Neg:case TK_Not:case TK_Add:case TK_Sub:{
case TK_Not:
case TK_Add:
case TK_Sub:{
Operand op = resolve_expr(node->expr); Operand op = resolve_expr(node->expr);
if(!is_numeric(op.type)) parsing_error(node->pos, "Unary [%s] cant be applied to value of type %s", token_kind_string(node->op).str, docname(op.type)); if(!is_numeric(op.type)) parsing_error(node->pos, "Unary [%s] cant be applied to value of type %s", token_kind_string(node->op).str, docname(op.type));
if(op.is_const){ if(op.is_const){
@@ -735,7 +745,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
Operand left = resolve_expr(node->left); Operand left = resolve_expr(node->left);
if(!left.is_lvalue) parsing_error(node->pos, "Assigning to rvalue"); if(!left.is_lvalue) parsing_error(node->pos, "Assigning to rvalue");
Operand right = resolve_expr(node->right); Operand right = resolve_expr(node->right);
try_untyping(&right);
right.value = convert_untyped(node->pos, right.value, left.type);
if(left.type != right.type) parsing_error(node->pos, "Can't assign value when left is %s and right is %s", docname(left.type), docname(right.type)); if(left.type != right.type) parsing_error(node->pos, "Can't assign value when left is %s and right is %s", docname(left.type), docname(right.type));
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -754,68 +765,74 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
} }
// @copy_paste // @copy_paste
if(is_pointer(type)) type = type->base; if(is_pointer(type)) type = type->base;
type_complete(type);
if(!(is_struct(type) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
sym_var({}, resolved_ident.type, node->left); sym_var({}, resolved_ident.type, node->left);
if(is_string(type) && !required_to_be_const){
// This happens only on binary nodes which further chain with dots and require lookups result = field_access_string(node->right);
// This part cant happen on enums
// x.resolve.y
Ast_Binary *binary = (Ast_Binary *)node->right;
for(;!is_ident(binary); binary=(Ast_Binary *)binary->right){
assert(is_ident(binary->left));
Ast_Atom *ident = (Ast_Atom *)binary->left;
assert(is_binary(binary));
Ast_Struct *agg = (Ast_Struct *)type->ast;
Ast *query = query_struct(agg, ident->intern_val);
if(query){
Sym *sym = resolved_get(query);
if(required_to_be_const && sym->kind != SYM_CONST) parsing_error(ident->pos, "Required to be constant");
type = sym->type;
// @copy_paste
if(type == type_type){
required_to_be_const = true;
type = sym->type_val;
}
if(is_pointer(type)) type = type->base;
type_complete(type);
if(!(is_struct(type) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
sym_associate(ident, sym);
} else parsing_error(ident->pos, "No such member in struct");
} }
else{
type_complete(type);
if(!(is_struct(type) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
// Here we can resolve the last part, this doesnt need to be a struct // This happens only on binary nodes which further chain with dots and require lookups
// x.y.resolve // This part cant happen on enums
// @copy_paste // x.resolve.y
Ast_Atom *ident = (Ast_Atom *)binary; Ast_Binary *binary = (Ast_Binary *)node->right;
if(is_enum(type)){ for(;!is_ident(binary); binary=(Ast_Binary *)binary->right){
Ast_Enum *enu = (Ast_Enum *)type->ast; assert(is_ident(binary->left));
Ast_Enum_Member *query = query_enum(enu, ident->intern_val); Ast_Atom *ident = (Ast_Atom *)binary->left;
if(query){ assert(is_binary(binary));
Sym *resolved = resolved_get(query);
assert(resolved); Ast_Struct *agg = (Ast_Struct *)type->ast;
rewrite_into_const(node, Ast_Binary, resolved); Ast *query = query_struct(agg, ident->intern_val);
result = operand(resolved); if(query){
Sym *sym = resolved_get(query);
if(required_to_be_const && sym->kind != SYM_CONST) parsing_error(ident->pos, "Required to be constant");
type = sym->type;
// @copy_paste
if(type == type_type){
required_to_be_const = true;
type = sym->type_val;
}
if(is_pointer(type)) type = type->base;
type_complete(type);
if(!(is_struct(type) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
sym_associate(ident, sym);
} else parsing_error(ident->pos, "No such member in struct");
} }
}
else if(is_struct(type)){
Ast_Struct *agg = (Ast_Struct *)type->ast;
Ast *query = query_struct(agg, ident->intern_val);
if(query){
Sym *sym = resolved_get(query);
result = operand(sym);
assert(sym);
if(sym->kind == SYM_CONST) rewrite_into_const(node, Ast_Binary, sym);
else sym_associate(ident, sym);
} else parsing_error(ident->pos, "No such member in struct"); // Here we can resolve the last part, this doesnt need to be a struct
} // x.y.resolve
else parsing_error(ident->pos, "Trying to [.] access a value that is not [Enum] or [Struct]"); // @copy_paste
Ast_Atom *ident = (Ast_Atom *)binary;
if(is_enum(type)){
Ast_Enum *enu = (Ast_Enum *)type->ast;
Ast_Enum_Member *query = query_enum(enu, ident->intern_val);
if(query){
Sym *resolved = resolved_get(query);
assert(resolved);
rewrite_into_const(node, Ast_Binary, resolved);
result = operand(resolved);
}
}
else if(is_struct(type)){
Ast_Struct *agg = (Ast_Struct *)type->ast;
Ast *query = query_struct(agg, ident->intern_val);
if(query){
Sym *sym = resolved_get(query);
result = operand(sym);
assert(sym);
if(sym->kind == SYM_CONST) rewrite_into_const(node, Ast_Binary, sym);
else sym_associate(ident, sym);
if(result.is_const == false && required_to_be_const){ } else parsing_error(ident->pos, "No such member in struct");
invalid_codepath; }
else parsing_error(ident->pos, "Trying to [.] access a value that is not [Enum] or [Struct]");
if(result.is_const == false && required_to_be_const){
invalid_codepath;
}
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -881,7 +898,7 @@ resolve_const(Ast_Expr *ast, Sym *sym){
value = op.int_val + 1; value = op.int_val + 1;
} }
else{ else{
op.type = type_int; op.type = type_s64;
op.int_val = value++; op.int_val = value++;
} }