Add string accessors, working towards first program
This commit is contained in:
25
ccodegen.cpp
25
ccodegen.cpp
@@ -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();
|
||||||
|
|||||||
16
lexer.kl
16
lexer.kl
@@ -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
|
|
||||||
|
|
||||||
*/
|
|
||||||
28
main.cpp
28
main.cpp
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,11 +193,15 @@ 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_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)){
|
||||||
cond = parse_expr();
|
cond = parse_expr();
|
||||||
if(token_match(TK_Comma)){
|
if(token_match(TK_Comma)){
|
||||||
@@ -205,6 +209,7 @@ parse_block(){
|
|||||||
iter = parse_init_stmt(iter);
|
iter = parse_init_stmt(iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ast_Block *for_block = parse_block();
|
Ast_Block *for_block = parse_block();
|
||||||
stmts.add(ast_for(token, init, cond, iter, for_block));
|
stmts.add(ast_for(token, init, cond, iter, for_block));
|
||||||
@@ -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){
|
||||||
|
|||||||
@@ -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)
|
|
||||||
|
|||||||
38
program.c
38
program.c
@@ -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
11
program.kl
Normal 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
|
||||||
@@ -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,9 +765,14 @@ 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;
|
||||||
|
|
||||||
|
sym_var({}, resolved_ident.type, node->left);
|
||||||
|
if(is_string(type) && !required_to_be_const){
|
||||||
|
result = field_access_string(node->right);
|
||||||
|
}
|
||||||
|
else{
|
||||||
type_complete(type);
|
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");
|
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);
|
|
||||||
|
|
||||||
// This happens only on binary nodes which further chain with dots and require lookups
|
// This happens only on binary nodes which further chain with dots and require lookups
|
||||||
// This part cant happen on enums
|
// This part cant happen on enums
|
||||||
@@ -818,6 +834,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
invalid_codepath;
|
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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user