Field access now works, somehow! It was easier then I thought,
probably introduced a bunch of bugs though
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# The Core Language
|
# The Core Language
|
||||||
|
|
||||||
A compiled language that assumes C as base reality but it also has lots of ideas taken from Jai, Go like type system, order indepent declarations using Ion algorithm. Syntax currently is whitespace significant. Made to practice language development, **it's not supposed to be used**. It has lot's of ideas from modern programming languages that you would not find in any compiler book. It supports **modules** combined with **ordered independent declarations** and **lazy typechecking**. Also **runtime reflection**, **slices** and other standard features you would find in C.
|
A compiled language that assumes C as base reality but it also has lots of ideas taken from Jai, Go like type system, order indepent declarations using Ion algorithm. Syntax currently is whitespace significant. Made to practice language development. It has lot's of ideas from modern programming languages that you would not find in any compiler book. It supports **modules** combined with **ordered independent declarations** and **lazy typechecking**. Also **runtime reflection**, **slices** and other standard features you would find in C.
|
||||||
|
|
||||||
The language is currently **very debuggable**. It can produce readable C code with line directives. This allows you to debug the programs with Visual Studio with full source mapping, exactly like you would debug C programs.
|
The language is currently **very debuggable**. It can produce readable C code with line directives. This allows you to debug the programs with Visual Studio with full source mapping, exactly like you would debug C programs.
|
||||||
|
|
||||||
|
|||||||
@@ -971,13 +971,14 @@ try_propagating_resolved_type_to_untyped_literals(Ast *ast, Ast_Type *type, Ast_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @todo: Remove compound context
|
||||||
function Ast_Type *
|
function Ast_Type *
|
||||||
resolve_typespec(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context = 0){
|
resolve_typespec(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context = 0){
|
||||||
if(!ast && is_flag_set(flags, AST_CAN_BE_NULL))
|
if(!ast && is_flag_set(flags, AST_CAN_BE_NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Operand resolved = resolve_expr(ast, flags | RESOLVE_TYPESPEC, compound_context);
|
Operand resolved = resolve_expr(ast, flags | RESOLVE_TYPESPEC, compound_context, 0);
|
||||||
if(is_flag_set(flags, RESOLVE_TYPESPEC_COMPLETE))
|
if(is_flag_set(flags, RESOLVE_TYPESPEC_COMPLETE))
|
||||||
type_complete(resolved.type_val);
|
type_complete(resolved.type_val);
|
||||||
if(resolved.type != type_type)
|
if(resolved.type != type_type)
|
||||||
@@ -985,6 +986,7 @@ resolve_typespec(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context =
|
|||||||
return resolved.type_val;
|
return resolved.type_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @todo: Remove compound context
|
||||||
function Operand
|
function Operand
|
||||||
resolve_and_require_bool(const char *error, Ast_Expr *expr, Resolve_Flag flags, Ast_Type *compound_context = 0){
|
resolve_and_require_bool(const char *error, Ast_Expr *expr, Resolve_Flag flags, Ast_Type *compound_context = 0){
|
||||||
if(!expr){
|
if(!expr){
|
||||||
@@ -994,7 +996,7 @@ resolve_and_require_bool(const char *error, Ast_Expr *expr, Resolve_Flag flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Operand op = resolve_expr(expr, flags, compound_context);
|
Operand op = resolve_expr(expr, flags, compound_context, 0);
|
||||||
if(!is_bool(op.type)){
|
if(!is_bool(op.type)){
|
||||||
compiler_error(expr->pos, "Expected type [Bool] got instead type %Q :: %s", typestring(op.type), error);
|
compiler_error(expr->pos, "Expected type [Bool] got instead type %Q :: %s", typestring(op.type), error);
|
||||||
}
|
}
|
||||||
@@ -1002,9 +1004,10 @@ resolve_and_require_bool(const char *error, Ast_Expr *expr, Resolve_Flag flags,
|
|||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @todo: Remove compound context
|
||||||
function Operand
|
function Operand
|
||||||
require_const_int(Ast_Expr *expr, Resolve_Flag flags, Ast_Type *compound_context = 0){
|
require_const_int(Ast_Expr *expr, Resolve_Flag flags, Ast_Type *compound_context = 0){
|
||||||
Operand op = resolve_expr(expr, flags, compound_context);
|
Operand op = resolve_expr(expr, flags, compound_context, 0);
|
||||||
|
|
||||||
if(expr == 0 && flags)
|
if(expr == 0 && flags)
|
||||||
return op;
|
return op;
|
||||||
@@ -1036,10 +1039,10 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
|||||||
Operand op;
|
Operand op;
|
||||||
if(is_tuple(ret)){
|
if(is_tuple(ret)){
|
||||||
Ast_Type *sub_type = ret->agg.members[it.i].type;
|
Ast_Type *sub_type = ret->agg.members[it.i].type;
|
||||||
op = resolve_expr(*it.item, AST_CAN_BE_NULL, sub_type);
|
op = resolve_expr(*it.item, AST_CAN_BE_NULL, sub_type, 0);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
op = resolve_expr(*it.item, AST_CAN_BE_NULL, ret);
|
op = resolve_expr(*it.item, AST_CAN_BE_NULL, ret, 0);
|
||||||
convert_untyped_to_typed(node->pos, &op.value, ret);
|
convert_untyped_to_typed(node->pos, &op.value, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1099,8 +1102,8 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_expr(node->init, AST_CAN_BE_NULL);
|
resolve_expr(node->init, AST_CAN_BE_NULL, 0, 0);
|
||||||
Operand op = resolve_expr(node->cond, AST_CAN_BE_NULL);
|
Operand op = resolve_expr(node->cond, AST_CAN_BE_NULL, 0, 0);
|
||||||
if(node->cond){
|
if(node->cond){
|
||||||
if((!node->init && !node->iter) && (is_array(op.type) || is_slice(op.type))){
|
if((!node->init && !node->iter) && (is_array(op.type) || is_slice(op.type))){
|
||||||
node->is_array_traversal = true;
|
node->is_array_traversal = true;
|
||||||
@@ -1120,7 +1123,7 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_expr(node->iter, AST_CAN_BE_NULL);
|
resolve_expr(node->iter, AST_CAN_BE_NULL, 0, 0);
|
||||||
For(node->scope->stmts) resolve_stmt(it, ret);
|
For(node->scope->stmts) resolve_stmt(it, ret);
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
@@ -1138,7 +1141,7 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(SWITCH, Switch){
|
CASE(SWITCH, Switch){
|
||||||
Operand base = resolve_expr(node->value, AST_CANT_BE_NULL);
|
Operand base = resolve_expr(node->value, AST_CANT_BE_NULL, 0, 0);
|
||||||
if(!is_int(base.type) && !is_enum(base.type))
|
if(!is_int(base.type) && !is_enum(base.type))
|
||||||
compiler_error(node->pos, "You can only switch on integer values(enums included), the type of expression in switch statement is instead %Q", typestring(base.type));
|
compiler_error(node->pos, "You can only switch on integer values(enums included), the type of expression in switch statement is instead %Q", typestring(base.type));
|
||||||
|
|
||||||
@@ -1146,7 +1149,7 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
|||||||
try_propagating_resolved_type_to_untyped_literals(node->value, base.type);
|
try_propagating_resolved_type_to_untyped_literals(node->value, base.type);
|
||||||
For(node->cases){
|
For(node->cases){
|
||||||
For_Named(it->labels, label){
|
For_Named(it->labels, label){
|
||||||
Operand op = resolve_expr(label, AST_CANT_BE_NULL);
|
Operand op = resolve_expr(label, AST_CANT_BE_NULL, 0, 0);
|
||||||
if(!op.is_const) compiler_error(label->pos, "Switch label required to be constant");
|
if(!op.is_const) compiler_error(label->pos, "Switch label required to be constant");
|
||||||
make_sure_value_is_compatible_with_type(label->pos, &op, base.type, TYPE_AND_EXPR_REQUIRED);
|
make_sure_value_is_compatible_with_type(label->pos, &op, base.type, TYPE_AND_EXPR_REQUIRED);
|
||||||
try_propagating_resolved_type_to_untyped_literals(label, base.type);
|
try_propagating_resolved_type_to_untyped_literals(label, base.type);
|
||||||
@@ -1163,7 +1166,7 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(VAR_UNPACK, Var_Unpack){
|
CASE(VAR_UNPACK, Var_Unpack){
|
||||||
Operand expr_op = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
Operand expr_op = resolve_expr(node->expr, AST_CANT_BE_NULL, 0, 0);
|
||||||
if(!is_tuple(expr_op.type))
|
if(!is_tuple(expr_op.type))
|
||||||
compiler_error(node->pos, "Expected expression to be of type [Tuple]");
|
compiler_error(node->pos, "Expected expression to be of type [Tuple]");
|
||||||
if(expr_op.type->agg.members.len != node->vars.len)
|
if(expr_op.type->agg.members.len != node->vars.len)
|
||||||
@@ -1183,7 +1186,7 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
|||||||
default:{
|
default:{
|
||||||
if(is_flag_set(ast->flags, AST_EXPR)){
|
if(is_flag_set(ast->flags, AST_EXPR)){
|
||||||
assert(is_flag_set(ast->flags, AST_STMT));
|
assert(is_flag_set(ast->flags, AST_STMT));
|
||||||
resolve_expr((Ast_Expr *)ast, AST_CANT_BE_NULL);
|
resolve_expr((Ast_Expr *)ast, AST_CANT_BE_NULL, 0, 0);
|
||||||
}
|
}
|
||||||
else invalid_codepath;
|
else invalid_codepath;
|
||||||
}
|
}
|
||||||
@@ -1213,7 +1216,7 @@ resolve_lambda_type(Ast_Lambda *lambda){
|
|||||||
|
|
||||||
else {
|
else {
|
||||||
Ast_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL);
|
Ast_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL);
|
||||||
Operand default_value = resolve_expr(it->expr, AST_CAN_BE_NULL, type);
|
Operand default_value = resolve_expr(it->expr, AST_CAN_BE_NULL, type, 0);
|
||||||
make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL);
|
make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL);
|
||||||
|
|
||||||
it->type = type;
|
it->type = type;
|
||||||
@@ -1245,7 +1248,7 @@ try_resolving_lambda_scope(Operand *op, Ast_Lambda *lambda, Ast_Type *lambda_typ
|
|||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
resolve_cast(Ast_Binary *node){
|
resolve_cast(Ast_Binary *node){
|
||||||
Operand expr = resolve_expr(node->left, AST_CANT_BE_NULL);
|
Operand expr = resolve_expr(node->left, AST_CANT_BE_NULL, 0, 0);
|
||||||
Ast_Type *type = resolve_typespec(node->right, AST_CANT_BE_NULL);
|
Ast_Type *type = resolve_typespec(node->right, AST_CANT_BE_NULL);
|
||||||
Ast_Type *original_type = expr.type;
|
Ast_Type *original_type = expr.type;
|
||||||
node->before_type = expr.type;
|
node->before_type = expr.type;
|
||||||
@@ -1330,7 +1333,7 @@ resolve_compound_array(Ast_Call *node, Ast_Type *type){
|
|||||||
it->resolved_index = default_counter;
|
it->resolved_index = default_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand item = resolve_expr(it->item, AST_CANT_BE_NULL, item_type);
|
Operand item = resolve_expr(it->item, AST_CANT_BE_NULL, item_type, 0);
|
||||||
make_sure_value_is_compatible_with_type(it->pos, &item, item_type, TYPE_AND_EXPR_REQUIRED);
|
make_sure_value_is_compatible_with_type(it->pos, &item, item_type, TYPE_AND_EXPR_REQUIRED);
|
||||||
it->resolved_type = item_type;
|
it->resolved_type = item_type;
|
||||||
try_propagating_resolved_type_to_untyped_literals(it->item, it->resolved_type);
|
try_propagating_resolved_type_to_untyped_literals(it->item, it->resolved_type);
|
||||||
@@ -1385,7 +1388,7 @@ resolve_compound_struct(Ast_Call *node, Ast_Type *type){
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(item_type);
|
assert(item_type);
|
||||||
Operand item = resolve_expr(it->item, AST_CANT_BE_NULL, item_type);
|
Operand item = resolve_expr(it->item, AST_CANT_BE_NULL, item_type, 0);
|
||||||
make_sure_value_is_compatible_with_type(it->pos, &item, item_type, TYPE_AND_EXPR_REQUIRED);
|
make_sure_value_is_compatible_with_type(it->pos, &item, item_type, TYPE_AND_EXPR_REQUIRED);
|
||||||
|
|
||||||
it->resolved_type = item_type;
|
it->resolved_type = item_type;
|
||||||
@@ -1395,49 +1398,6 @@ resolve_compound_struct(Ast_Call *node, Ast_Type *type){
|
|||||||
For(type->agg.members) it.visited = false;
|
For(type->agg.members) it.visited = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Operand
|
|
||||||
resolve_field_access(Ast_Expr *node, Ast_Scope *context){
|
|
||||||
Ast_Binary *current = 0;
|
|
||||||
Ast_Expr *next = 0;
|
|
||||||
if(node->kind == AST_BINARY){
|
|
||||||
current = (Ast_Binary *)node;
|
|
||||||
next = current->right;
|
|
||||||
node = current->left;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(node->kind != AST_IDENT)
|
|
||||||
compiler_error(node->pos, "Required to be identifier in field access");
|
|
||||||
|
|
||||||
Ast_Atom *ident = (Ast_Atom *)node;
|
|
||||||
Ast_Scope *scope = context ? context : node->parent_scope;
|
|
||||||
Search_Flag flag = context ? SEARCH_ONLY_CURRENT_SCOPE : 0;
|
|
||||||
Ast_Decl *decl = resolve_name(scope, node->pos, ident->intern_val, flag);
|
|
||||||
ident->resolved_decl = decl;
|
|
||||||
if(decl->kind == AST_FILE_NAMESPACE || decl->kind == AST_MODULE_NAMESPACE){
|
|
||||||
assert(next);
|
|
||||||
return resolve_field_access(next, decl->scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ast_Type *type = decl->type;
|
|
||||||
if(type == type_type && decl->type_val && (is_enum(decl->type_val) || is_struct(decl->type_val)))
|
|
||||||
type = decl->type_val;
|
|
||||||
if(current) current->dot_access_step_resolution = type;
|
|
||||||
if(is_pointer(type)) type = type->base;
|
|
||||||
|
|
||||||
type_complete(type);
|
|
||||||
if(next && !is_struct(type) && !is_enum(type)){
|
|
||||||
compiler_error(node->pos, "Dot access");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!next){
|
|
||||||
Operand op = operand(decl);
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(next);
|
|
||||||
return resolve_field_access(next, ((Ast_Decl *)type->ast)->scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Ast_Expr *
|
function Ast_Expr *
|
||||||
unpack_ast_call_expr_for_builtin(Ast_Call *call){
|
unpack_ast_call_expr_for_builtin(Ast_Call *call){
|
||||||
if(call->exprs.len != 1) {
|
if(call->exprs.len != 1) {
|
||||||
@@ -1459,7 +1419,7 @@ expr_atom_is_equal_intern(Ast_Expr *expr, Intern_String intern){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context, Ast_Scope *field_access_scope){
|
||||||
if(!ast && is_flag_set(flags, AST_CAN_BE_NULL)) return {};
|
if(!ast && is_flag_set(flags, AST_CAN_BE_NULL)) return {};
|
||||||
assert(is_flag_set(ast->flags, AST_EXPR));
|
assert(is_flag_set(ast->flags, AST_EXPR));
|
||||||
assert(ast->parent_scope->kind == AST_SCOPE || ast->parent_scope->kind == AST_FILE);
|
assert(ast->parent_scope->kind == AST_SCOPE || ast->parent_scope->kind == AST_FILE);
|
||||||
@@ -1467,7 +1427,10 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
|
|
||||||
CASE(IDENT, Atom){
|
CASE(IDENT, Atom){
|
||||||
node->resolved_decl = resolve_name(node->parent_scope, node->pos, node->intern_val);
|
Ast_Scope *scope = field_access_scope ? field_access_scope : node->parent_scope;
|
||||||
|
Search_Flag flag = field_access_scope ? SEARCH_ONLY_CURRENT_SCOPE : 0;
|
||||||
|
|
||||||
|
node->resolved_decl = resolve_name(scope, node->pos, node->intern_val, flag);
|
||||||
node->resolved_type = node->resolved_decl->type;
|
node->resolved_type = node->resolved_decl->type;
|
||||||
|
|
||||||
Operand result = operand(node->resolved_decl);
|
Operand result = operand(node->resolved_decl);
|
||||||
@@ -1485,7 +1448,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
|
|
||||||
// Typespec array [32]int
|
// Typespec array [32]int
|
||||||
CASE(ARRAY, Array){
|
CASE(ARRAY, Array){
|
||||||
Operand type = resolve_expr(node->base, AST_CANT_BE_NULL);
|
Operand type = resolve_expr(node->base, AST_CANT_BE_NULL, 0, 0);
|
||||||
Operand expr = require_const_int(node->expr, AST_CAN_BE_NULL);
|
Operand expr = require_const_int(node->expr, AST_CAN_BE_NULL);
|
||||||
if(type.type != type_type) compiler_error(node->pos, "Prefix array operator is only allowed on types");
|
if(type.type != type_type) compiler_error(node->pos, "Prefix array operator is only allowed on types");
|
||||||
type_complete(type.type_val);
|
type_complete(type.type_val);
|
||||||
@@ -1517,8 +1480,8 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(INDEX, Index){
|
CASE(INDEX, Index){
|
||||||
Operand left = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
Operand left = resolve_expr(node->expr, AST_CANT_BE_NULL , 0, field_access_scope);
|
||||||
Operand index = resolve_expr(node->index, AST_CANT_BE_NULL);
|
Operand index = resolve_expr(node->index, AST_CANT_BE_NULL, 0, 0);
|
||||||
if(!is_int(index.type))
|
if(!is_int(index.type))
|
||||||
compiler_error(node->pos, "Trying to index the array with invalid type, expected [Int] got instead %Q", typestring(index.type));
|
compiler_error(node->pos, "Trying to index the array with invalid type, expected [Int] got instead %Q", typestring(index.type));
|
||||||
|
|
||||||
@@ -1556,9 +1519,9 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
CASE(BINARY, Binary){
|
CASE(BINARY, Binary){
|
||||||
if(token_is_assign(node->op)){
|
if(token_is_assign(node->op)){
|
||||||
assert(is_flag_set(node->flags, AST_STMT));
|
assert(is_flag_set(node->flags, AST_STMT));
|
||||||
Operand left = resolve_expr(node->left, AST_CANT_BE_NULL);
|
Operand left = resolve_expr(node->left, AST_CANT_BE_NULL, 0, field_access_scope);
|
||||||
if(!left.is_lvalue) compiler_error(node->pos, "Assigning to rvalue");
|
if(!left.is_lvalue) compiler_error(node->pos, "Assigning to rvalue");
|
||||||
Operand right = resolve_expr(node->right, AST_CANT_BE_NULL);
|
Operand right = resolve_expr(node->right, AST_CANT_BE_NULL, 0, field_access_scope);
|
||||||
|
|
||||||
convert_untyped_to_typed(node->pos, &right.value, left.type);
|
convert_untyped_to_typed(node->pos, &right.value, left.type);
|
||||||
if(left.type != right.type) compiler_error(node->pos, "Can't assign value when left is %Q and right is %Q", typestring(left.type), typestring(right.type));
|
if(left.type != right.type) compiler_error(node->pos, "Can't assign value when left is %Q and right is %Q", typestring(left.type), typestring(right.type));
|
||||||
@@ -1572,17 +1535,45 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
return resolve_cast(node);
|
return resolve_cast(node);
|
||||||
}
|
}
|
||||||
else if(node->op == TK_Dot){
|
else if(node->op == TK_Dot){
|
||||||
Operand op = resolve_field_access(node, 0);
|
Operand left = resolve_expr(node->left, AST_CANT_BE_NULL, 0, field_access_scope);
|
||||||
node->resolved_type = op.type;
|
Ast_Scope *scope = 0;
|
||||||
|
|
||||||
if(op.is_const){
|
Ast_Decl *decl = left.resolved_decl;
|
||||||
rewrite_into_const(node, Ast_Binary, op.value);
|
if(decl && (decl->kind == AST_FILE_NAMESPACE || decl->kind == AST_MODULE_NAMESPACE)){
|
||||||
|
scope = decl->scope;
|
||||||
}
|
}
|
||||||
return op;
|
|
||||||
|
else {
|
||||||
|
// Make sure it's a type but also not a type id
|
||||||
|
Ast_Type *type = left.type;
|
||||||
|
if(type == type_type && left.type_val){
|
||||||
|
if(is_enum(left.type_val) || is_struct(left.type_val)){
|
||||||
|
type = left.type_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need 2 resolved types, for left and right
|
||||||
|
// Then we can compare if we got a pointer we need to
|
||||||
|
// figure that out to replace '.' with '->' for pointer structs
|
||||||
|
node->dot_access_step_resolution = type;
|
||||||
|
|
||||||
|
if(is_pointer(type)) type = type->base;
|
||||||
|
type_complete(type);
|
||||||
|
|
||||||
|
scope = ((Ast_Decl *)type->ast)->scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand right = resolve_expr(node->right, AST_CANT_BE_NULL, 0, scope);
|
||||||
|
node->resolved_type = right.type;
|
||||||
|
|
||||||
|
if(right.is_const){
|
||||||
|
rewrite_into_const(node, Ast_Binary, right.value);
|
||||||
|
}
|
||||||
|
return right;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
Operand left = resolve_expr(node->left, AST_CANT_BE_NULL);
|
Operand left = resolve_expr(node->left, AST_CANT_BE_NULL, 0, field_access_scope);
|
||||||
Operand right = resolve_expr(node->right, AST_CANT_BE_NULL);
|
Operand right = resolve_expr(node->right, AST_CANT_BE_NULL, 0, field_access_scope);
|
||||||
B32 is_const = left.is_const && right.is_const;
|
B32 is_const = left.is_const && right.is_const;
|
||||||
B32 proceed_to_default_operator_handler = true;
|
B32 proceed_to_default_operator_handler = true;
|
||||||
|
|
||||||
@@ -1629,7 +1620,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(UNARY, Unary){
|
CASE(UNARY, Unary){
|
||||||
Operand value = resolve_expr(node->expr, inherit_flag(flags, AST_CANT_BE_NULL));
|
Operand value = resolve_expr(node->expr, inherit_flag(flags, AST_CANT_BE_NULL), 0, field_access_scope);
|
||||||
if(node->op == TK_Pointer){
|
if(node->op == TK_Pointer){
|
||||||
if(value.type->kind == TYPE_POINTER){
|
if(value.type->kind == TYPE_POINTER){
|
||||||
node->resolved_type = value.type->base;
|
node->resolved_type = value.type->base;
|
||||||
@@ -1685,7 +1676,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(COMPOUND, Call){
|
CASE(COMPOUND, Call){
|
||||||
Operand op = resolve_expr(node->typespec, inherit_flag(flags, AST_CAN_BE_NULL));
|
Operand op = resolve_expr(node->typespec, inherit_flag(flags, AST_CAN_BE_NULL), 0, field_access_scope);
|
||||||
|
|
||||||
Ast_Type *type = op.type;
|
Ast_Type *type = op.type;
|
||||||
if(type){
|
if(type){
|
||||||
@@ -1716,7 +1707,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
if(expr_atom_is_equal_intern(node->name, intern_sizeof)){
|
if(expr_atom_is_equal_intern(node->name, intern_sizeof)){
|
||||||
Ast_Expr *expr = unpack_ast_call_expr_for_builtin(node);
|
Ast_Expr *expr = unpack_ast_call_expr_for_builtin(node);
|
||||||
|
|
||||||
Operand name = resolve_expr(expr, inherit_flag(flags, AST_CANT_BE_NULL));
|
Operand name = resolve_expr(expr, inherit_flag(flags, AST_CANT_BE_NULL), 0, field_access_scope);
|
||||||
node->kind = AST_SIZE_OF;
|
node->kind = AST_SIZE_OF;
|
||||||
if(!name.is_const){
|
if(!name.is_const){
|
||||||
compiler_error(node->pos, "SizeOf requires a constant value");
|
compiler_error(node->pos, "SizeOf requires a constant value");
|
||||||
@@ -1736,7 +1727,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
else if(expr_atom_is_equal_intern(node->name, intern_len)){
|
else if(expr_atom_is_equal_intern(node->name, intern_len)){
|
||||||
Ast_Expr *expr = unpack_ast_call_expr_for_builtin(node);
|
Ast_Expr *expr = unpack_ast_call_expr_for_builtin(node);
|
||||||
|
|
||||||
Operand name = resolve_expr(expr, inherit_flag(flags, AST_CANT_BE_NULL));
|
Operand name = resolve_expr(expr, inherit_flag(flags, AST_CANT_BE_NULL), 0, field_access_scope);
|
||||||
node->kind = AST_LENGTH_OF;
|
node->kind = AST_LENGTH_OF;
|
||||||
node->resolved_type = type_s64;
|
node->resolved_type = type_s64;
|
||||||
if(is_array(name.type)){
|
if(is_array(name.type)){
|
||||||
@@ -1757,7 +1748,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
|
|
||||||
else if(expr_atom_is_equal_intern(node->name, intern_alignof)){
|
else if(expr_atom_is_equal_intern(node->name, intern_alignof)){
|
||||||
Ast_Expr *expr = unpack_ast_call_expr_for_builtin(node);
|
Ast_Expr *expr = unpack_ast_call_expr_for_builtin(node);
|
||||||
Operand name = resolve_expr(expr, inherit_flag(flags, AST_CANT_BE_NULL));
|
Operand name = resolve_expr(expr, inherit_flag(flags, AST_CANT_BE_NULL), 0, field_access_scope);
|
||||||
node->kind = AST_ALIGN_OF;
|
node->kind = AST_ALIGN_OF;
|
||||||
if(!name.is_const) {
|
if(!name.is_const) {
|
||||||
compiler_error(node->pos, "AlignOf requires a constant value");
|
compiler_error(node->pos, "AlignOf requires a constant value");
|
||||||
@@ -1775,7 +1766,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
Operand name = resolve_expr(node->name, inherit_flag(flags, AST_CANT_BE_NULL));
|
Operand name = resolve_expr(node->name, inherit_flag(flags, AST_CANT_BE_NULL), 0, field_access_scope);
|
||||||
if(name.type->kind != TYPE_LAMBDA){
|
if(name.type->kind != TYPE_LAMBDA){
|
||||||
compiler_error(node->pos, "Calling %Q which is not a [Lambda]", typestring(name.type));
|
compiler_error(node->pos, "Calling %Q which is not a [Lambda]", typestring(name.type));
|
||||||
}
|
}
|
||||||
@@ -1823,7 +1814,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
|
|
||||||
if(item){
|
if(item){
|
||||||
set_flag(item->call_flags, CALL_INCLUDED);
|
set_flag(item->call_flags, CALL_INCLUDED);
|
||||||
Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL, lambda_arg->type);
|
Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL, lambda_arg->type, field_access_scope);
|
||||||
if(is_flag_set(lambda_arg->flags, AST_ANY_VARGS)){
|
if(is_flag_set(lambda_arg->flags, AST_ANY_VARGS)){
|
||||||
make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type->base, TYPE_AND_EXPR_REQUIRED);
|
make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type->base, TYPE_AND_EXPR_REQUIRED);
|
||||||
item->resolved_type = expr.type;
|
item->resolved_type = expr.type;
|
||||||
@@ -1930,7 +1921,7 @@ resolve_decl(Ast_Decl *ast){
|
|||||||
CASE(CONST, Decl){
|
CASE(CONST, Decl){
|
||||||
// @warning: if in the future we add type here then pass it to resolve expr for
|
// @warning: if in the future we add type here then pass it to resolve expr for
|
||||||
// compound
|
// compound
|
||||||
Operand op = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
Operand op = resolve_expr(node->expr, AST_CANT_BE_NULL, 0, 0);
|
||||||
if(!op.is_const){
|
if(!op.is_const){
|
||||||
compiler_error(node->pos, "Assigning a value that is not constant to a constant declaration");
|
compiler_error(node->pos, "Assigning a value that is not constant to a constant declaration");
|
||||||
}
|
}
|
||||||
@@ -1950,7 +1941,7 @@ resolve_decl(Ast_Decl *ast){
|
|||||||
CASE(VAR, Decl){
|
CASE(VAR, Decl){
|
||||||
Ast_Type *type = node->type;
|
Ast_Type *type = node->type;
|
||||||
if(!type) type = resolve_typespec(node->typespec, AST_CAN_BE_NULL | RESOLVE_TYPESPEC_COMPLETE);
|
if(!type) type = resolve_typespec(node->typespec, AST_CAN_BE_NULL | RESOLVE_TYPESPEC_COMPLETE);
|
||||||
Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL, type);
|
Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL, type, 0);
|
||||||
assert(op.type != 0 || type != 0);
|
assert(op.type != 0 || type != 0);
|
||||||
|
|
||||||
make_sure_value_is_compatible_with_type(node->pos, &op, type, EXPR_CAN_BE_NULL|TYPE_CAN_BE_NULL);
|
make_sure_value_is_compatible_with_type(node->pos, &op, type, EXPR_CAN_BE_NULL|TYPE_CAN_BE_NULL);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ enum{
|
|||||||
SEARCH_ONLY_CURRENT_SCOPE = bit_flag(1),
|
SEARCH_ONLY_CURRENT_SCOPE = bit_flag(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
function Operand resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context = 0);
|
function Operand resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context, Ast_Scope *field_access_scope);
|
||||||
function void resolve_decl(Ast_Decl *ast);
|
function void resolve_decl(Ast_Decl *ast);
|
||||||
function Ast_Decl *resolve_name(Ast_Scope *parent_scope, Token *pos, Intern_String name, Search_Flag search_flags = 0);
|
function Ast_Decl *resolve_name(Ast_Scope *parent_scope, Token *pos, Intern_String name, Search_Flag search_flags = 0);
|
||||||
function String gen_string_simple_decl(Allocator *a, Ast_Type *ast, String name = {}, Ast_Scope *scope = 0, bool scope_names = true);
|
function String gen_string_simple_decl(Allocator *a, Ast_Type *ast, String name = {}, Ast_Scope *scope = 0, bool scope_names = true);
|
||||||
|
|||||||
9
examples/any_and_variadic_args.core
Normal file
9
examples/any_and_variadic_args.core
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
main :: (): int
|
||||||
|
a := 10
|
||||||
|
b := 20
|
||||||
|
values := []Any{a, b}
|
||||||
|
|
||||||
|
c := values[0].data
|
||||||
|
|
||||||
|
return 0
|
||||||
Reference in New Issue
Block a user