Compiling with new untyped system
This commit is contained in:
2211
big_int_c3.cpp
Normal file
2211
big_int_c3.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -73,10 +73,9 @@ gen_expr(Ast_Expr *ast){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(VALUE, Atom){
|
CASE(VALUE, Atom){
|
||||||
if(is_int(node->type)) gen("%lld", node->int_val);
|
if(is_int(node->type)) gen("%lld", bigint_as_signed(&node->big_int_val));
|
||||||
else if(is_string(node->type)) gen("LIT(\"%s\")", node->intern_val.str);
|
else if(is_string(node->type)) gen("LIT(\"%s\")", node->intern_val.str);
|
||||||
else if(is_bool(node->type)) node->bool_val ? gen("true"):gen("false");
|
else if(is_bool(node->type)) node->bool_val ? gen("true"):gen("false");
|
||||||
else if(is_f32(node->type)) gen("%f", node->f32_val);
|
|
||||||
else if(is_float(node->type)) gen("%f", node->f64_val);
|
else if(is_float(node->type)) gen("%f", node->f64_val);
|
||||||
else invalid_codepath;
|
else invalid_codepath;
|
||||||
BREAK();
|
BREAK();
|
||||||
@@ -315,7 +314,7 @@ gen_ast(Ast *ast){
|
|||||||
gen("// constant F64 %s = %f;", node->name.str, sym->f64_val);
|
gen("// constant F64 %s = %f;", node->name.str, sym->f64_val);
|
||||||
}
|
}
|
||||||
else if(sym->type == untyped_int){
|
else if(sym->type == untyped_int){
|
||||||
gen("// constant int %s = %lld;", node->name.str, sym->int_val);
|
gen("// constant int %s = %lld;", node->name.str, bigint_as_signed(&sym->big_int_val));
|
||||||
}
|
}
|
||||||
else if(sym->type == untyped_string){
|
else if(sym->type == untyped_string){
|
||||||
gen("// const String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str);
|
gen("// const String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str);
|
||||||
@@ -356,7 +355,7 @@ gen_ast(Ast *ast){
|
|||||||
genln("%s", it->name.str);
|
genln("%s", it->name.str);
|
||||||
gen(" = ");
|
gen(" = ");
|
||||||
Sym *value_sym = resolved_get(it);
|
Sym *value_sym = resolved_get(it);
|
||||||
gen("%d", value_sym->int_val);
|
gen("%d", bigint_as_signed(&value_sym->big_int_val));
|
||||||
gen(",");
|
gen(",");
|
||||||
}
|
}
|
||||||
global_indent--;
|
global_indent--;
|
||||||
|
|||||||
8
main.cpp
8
main.cpp
@@ -63,6 +63,7 @@ For now I don't thing it should be overloadable.
|
|||||||
[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] - More basic types
|
||||||
|
[x] - Implementing required operations int128
|
||||||
[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
|
||||||
@@ -94,15 +95,17 @@ For now I don't thing it should be overloadable.
|
|||||||
#include "base_unicode.cpp"
|
#include "base_unicode.cpp"
|
||||||
#include "new_lex.cpp"
|
#include "new_lex.cpp"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "big_int_c3.cpp"
|
||||||
|
// #include "big_int.cpp"
|
||||||
#include "new_ast.cpp"
|
#include "new_ast.cpp"
|
||||||
#include "new_parse.cpp"
|
#include "new_parse.cpp"
|
||||||
#include "typecheck.h"
|
#include "typecheck.h"
|
||||||
#include "typecheck.cpp"
|
#include "typecheck.cpp"
|
||||||
#include "ccodegen.cpp"
|
#include "ccodegen.cpp"
|
||||||
|
|
||||||
#include "big_int.cpp"
|
|
||||||
int main(){
|
int main(){
|
||||||
test_big_int();
|
// test_big_int();
|
||||||
|
|
||||||
|
|
||||||
test_os_memory();
|
test_os_memory();
|
||||||
thread_ctx_init();
|
thread_ctx_init();
|
||||||
@@ -114,6 +117,7 @@ int main(){
|
|||||||
test_string_builder();
|
test_string_builder();
|
||||||
test_intern_table();
|
test_intern_table();
|
||||||
|
|
||||||
|
|
||||||
String result = {};
|
String result = {};
|
||||||
#if 0
|
#if 0
|
||||||
result = compile_file("globals.kl"_s);
|
result = compile_file("globals.kl"_s);
|
||||||
|
|||||||
19
new_ast.cpp
19
new_ast.cpp
@@ -141,22 +141,13 @@ Ast_Resolved_Type *type; \
|
|||||||
union{ \
|
union{ \
|
||||||
bool bool_val; \
|
bool bool_val; \
|
||||||
F64 f64_val; \
|
F64 f64_val; \
|
||||||
F32 f32_val; \
|
Intern_String intern_val;\
|
||||||
S8 s8_val; \
|
BigInt big_int_val;\
|
||||||
S16 s16_val; \
|
|
||||||
S32 s32_val; \
|
|
||||||
S64 s64_val; \
|
|
||||||
U8 u8_val; \
|
|
||||||
U16 u16_val; \
|
|
||||||
U32 u32_val; \
|
|
||||||
U64 u64_val; \
|
|
||||||
S64 int_val; \
|
|
||||||
U64 uint_val; \
|
|
||||||
Intern_String intern_val; \
|
|
||||||
Ast_Resolved_Type *type_val; \
|
Ast_Resolved_Type *type_val; \
|
||||||
};
|
};
|
||||||
#define INLINE_VALUE_FIELDS union{Value value; struct{VALUE_FIELDS};}
|
#define INLINE_VALUE_FIELDS union{Value value; struct{VALUE_FIELDS};}
|
||||||
struct Value{VALUE_FIELDS};
|
struct Value{VALUE_FIELDS};
|
||||||
|
// BigInt big_int_val;
|
||||||
|
|
||||||
struct Ast_Atom: Ast_Expr{
|
struct Ast_Atom: Ast_Expr{
|
||||||
INLINE_VALUE_FIELDS;
|
INLINE_VALUE_FIELDS;
|
||||||
@@ -326,11 +317,9 @@ ast_float(Token *pos, F64 value){
|
|||||||
|
|
||||||
function Ast_Atom *
|
function Ast_Atom *
|
||||||
ast_int(Token *pos, U64 integer){
|
ast_int(Token *pos, U64 integer){
|
||||||
assert(integer <= S64MAX);
|
|
||||||
AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
|
AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
|
||||||
result->type = untyped_int;
|
result->type = untyped_int;
|
||||||
result->int_val = integer;
|
bigint_init_unsigned(&result->big_int_val, integer);
|
||||||
// result->big_int = big_int(pctx->perm, integer); // @todo: int arena??
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
450
typecheck.cpp
450
typecheck.cpp
@@ -31,13 +31,6 @@ type_error(Token *token, Ast_Resolved_Type *expected, Ast_Resolved_Type *actual,
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Evaluating constant expressions
|
// Evaluating constant expressions
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#define CASE_CONVERT(pos, int_val, kind_val, new_val, TYPE, min, max) \
|
|
||||||
case TYPE:{ \
|
|
||||||
if(int_val > max) parsing_error(pos, "Overflow when converting from %s constant to %s, value out of range: %d, max is: %d", type_names[kind_val], type_names[TYPE], int_val, max); \
|
|
||||||
if(int_val < min) parsing_error(pos, "Underflow when converting from %s constant to %s, value out of range: %d, min is: %d", type_names[kind_val], type_names[TYPE], int_val, min);\
|
|
||||||
new_val = int_val;\
|
|
||||||
}break;
|
|
||||||
|
|
||||||
function Value
|
function Value
|
||||||
convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
|
convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
|
||||||
// assert(a.type);
|
// assert(a.type);
|
||||||
@@ -45,37 +38,18 @@ convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
|
|||||||
if(a.type == 0) return a;
|
if(a.type == 0) return a;
|
||||||
if(is_typed(a.type)) return a;
|
if(is_typed(a.type)) return a;
|
||||||
|
|
||||||
assert(a.int_val <= S64MAX);
|
|
||||||
if(is_int(a.type) && is_int(new_type)){
|
if(is_int(a.type) && is_int(new_type)){
|
||||||
assert(a.type == untyped_int);
|
assert(a.type == untyped_int);
|
||||||
switch(new_type->kind){
|
if(!bigint_fits_in_bits(&a.big_int_val, new_type->size*8, is_signed_int(new_type))){
|
||||||
case TYPE_UNTYPED_INT: break;
|
parsing_error(pos, "Doesn't fit");
|
||||||
CASE_CONVERT(pos, a.int_val, a.type->kind, a.s64_val, TYPE_INT, TYPE_INT_MIN, TYPE_INT_MAX)
|
|
||||||
CASE_CONVERT(pos, a.int_val, a.type->kind, a.u64_val, TYPE_UINT, TYPE_UINT_MIN, TYPE_INT_MAX) // @todo big int
|
|
||||||
CASE_CONVERT(pos, a.int_val, a.type->kind, a.s8_val , TYPE_S8 , S8MIN, S8MAX)
|
|
||||||
CASE_CONVERT(pos, a.int_val, a.type->kind, a.s16_val, TYPE_S16, S16MIN, S16MAX)
|
|
||||||
CASE_CONVERT(pos, a.int_val, a.type->kind, a.s32_val, TYPE_S32, S32MIN, S32MAX)
|
|
||||||
CASE_CONVERT(pos, a.int_val, a.type->kind, a.s64_val, TYPE_S64, S64MIN, S64MAX)
|
|
||||||
CASE_CONVERT(pos, a.int_val, a.type->kind, a.u8_val , TYPE_U8 , U8MIN, U8MAX)
|
|
||||||
CASE_CONVERT(pos, a.int_val, a.type->kind, a.u16_val, TYPE_U16, U16MIN, U16MAX)
|
|
||||||
CASE_CONVERT(pos, a.int_val, a.type->kind, a.u32_val, TYPE_U32, U32MIN, U32MAX)
|
|
||||||
CASE_CONVERT(pos, a.int_val, a.type->kind, a.u64_val, TYPE_U64, U64MIN, U64MAX) // @todo big int
|
|
||||||
invalid_default_case;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(is_int(a.type) && is_float(new_type)){
|
else if(is_int(a.type) && is_float(new_type)){
|
||||||
assert(a.type == untyped_int);
|
a.f64_val = bigint_as_float(&a.big_int_val); // @leak bigint
|
||||||
switch(new_type->kind){
|
|
||||||
case TYPE_F32: {a.f32_val = a.int_val;}break;
|
|
||||||
case TYPE_UNTYPED_FLOAT:{a.f64_val = a.int_val;}break;
|
|
||||||
case TYPE_F64: {a.f64_val = a.int_val;}break;
|
|
||||||
invalid_default_case;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(is_float(a.type) && is_float(new_type)){
|
else if(is_float(a.type) && is_float(new_type)){
|
||||||
assert(a.type == untyped_float);
|
// nothing to do
|
||||||
if(new_type == type_f32) a.f32_val = a.f64_val;
|
|
||||||
}
|
}
|
||||||
else if(is_bool(a.type) && is_bool(new_type))
|
else if(is_bool(a.type) && is_bool(new_type))
|
||||||
; // nothing to do
|
; // nothing to do
|
||||||
@@ -87,193 +61,208 @@ convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
function S64
|
|
||||||
value_get_int(Value value){
|
function Value
|
||||||
assert(value.int_val <= S64MAX);
|
value_bool(B32 v){
|
||||||
assert(is_numeric(value.type));
|
Value value;
|
||||||
S64 result = 0;
|
value.bool_val = v;
|
||||||
switch(value.type->kind){
|
value.type = untyped_bool;
|
||||||
case TYPE_BOOL: result = value.bool_val; break;
|
return value;
|
||||||
case TYPE_UNTYPED_BOOL: result = value.bool_val; break;
|
}
|
||||||
case TYPE_UNTYPED_FLOAT: result = (S64)value.f64_val; break;
|
|
||||||
case TYPE_F64: result = (S64)value.f64_val; break;
|
function Value
|
||||||
case TYPE_F32: result = (S64)value.f32_val; break;
|
value_int(BigInt b){
|
||||||
case TYPE_UNTYPED_INT: result = value.int_val; break;
|
Value value;
|
||||||
case TYPE_INT: result = value.s64_val; break;
|
value.big_int_val = b;
|
||||||
case TYPE_S64:result = value.s64_val; break;
|
value.type = untyped_int;
|
||||||
case TYPE_S32:result = value.s32_val; break;
|
return value;
|
||||||
case TYPE_S16:result = value.s16_val; break;
|
}
|
||||||
case TYPE_S8:result = value.s8_val; break;
|
|
||||||
case TYPE_U64:assert(value.u64_val <= S64MAX); result = value.u64_val; break; // @todo big int
|
function Value
|
||||||
case TYPE_U32:result = value.u32_val; break;
|
value_int(S64 s64){
|
||||||
case TYPE_U16:result = value.u16_val; break;
|
Value value;
|
||||||
case TYPE_U8:result = value.u8_val; break;
|
value.type = untyped_int;
|
||||||
case TYPE_UINT:result = value.u64_val; break; // @todo big int
|
bigint_init_signed(&value.big_int_val, s64);
|
||||||
default: invalid_codepath;
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Value
|
||||||
|
value_float(F64 b){
|
||||||
|
Value value;
|
||||||
|
value.f64_val = b;
|
||||||
|
value.type = untyped_float;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Value
|
||||||
|
value_float(BigInt a){
|
||||||
|
Value value;
|
||||||
|
value.f64_val = bigint_as_float(&a);
|
||||||
|
value.type = untyped_float;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
match_values(Value *a, Value *b){
|
||||||
|
if(is_int(a->type) && is_float(b->type)){
|
||||||
|
*a = value_float(a->big_int_val);
|
||||||
|
}
|
||||||
|
else if(is_float(a->type) && is_int(b->type)){
|
||||||
|
*b = value_float(b->big_int_val);
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function F64
|
function Value
|
||||||
value_get_float(Value value){
|
compare_values(Token *pos, Token_Kind op, Value a, Value b){
|
||||||
assert(is_numeric(value.type));
|
if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(a.type));
|
||||||
F64 result = value.f64_val;
|
match_values(&a, &b);
|
||||||
if(is_int(value.type) || is_bool(value.type))
|
|
||||||
result = (F64)value_get_int(value);
|
B32 result = 0;
|
||||||
else if(value.type == type_f32)
|
switch(a.type->kind){
|
||||||
result = value.f32_val;
|
case TYPE_UNTYPED_INT:
|
||||||
return result;
|
case TYPE_S8:case TYPE_S16:case TYPE_S32:case TYPE_S64:
|
||||||
|
case TYPE_U8:case TYPE_U16:case TYPE_U32:case TYPE_U64:{
|
||||||
|
CmpRes cmp = bigint_cmp(&a.big_int_val, &b.big_int_val);
|
||||||
|
switch(op){
|
||||||
|
case TK_LesserThenOrEqual: result = (cmp == CMP_LT) || (cmp == CMP_EQ); break;
|
||||||
|
case TK_GreaterThenOrEqual: result = (cmp == CMP_GT) || (cmp == CMP_EQ); break;
|
||||||
|
case TK_GreaterThen: result = cmp == CMP_GT; break;
|
||||||
|
case TK_LesserThen: result = cmp == CMP_LT; break;
|
||||||
|
case TK_Equals: result = cmp == CMP_EQ; break;
|
||||||
|
case TK_NotEquals: result = cmp != CMP_EQ; break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
case TYPE_UNTYPED_BOOL:
|
||||||
|
case TYPE_BOOL:{
|
||||||
|
switch(op){
|
||||||
|
case TK_Equals: result = a.bool_val == b.bool_val; break;
|
||||||
|
case TK_NotEquals: result = a.bool_val != b.bool_val; break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
case TYPE_UNTYPED_FLOAT:
|
||||||
|
case TYPE_F32: case TYPE_F64:{
|
||||||
|
switch(op){
|
||||||
|
case TK_LesserThenOrEqual: result = a.f64_val <= b.f64_val; break;
|
||||||
|
case TK_GreaterThenOrEqual: result = a.f64_val >= b.f64_val; break;
|
||||||
|
case TK_GreaterThen: result = a.f64_val > b.f64_val; break;
|
||||||
|
case TK_LesserThen: result = a.f64_val < b.f64_val; break;
|
||||||
|
case TK_Equals: result = a.f64_val == b.f64_val; break;
|
||||||
|
case TK_NotEquals: result = a.f64_val != b.f64_val; break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
case TYPE_UNTYPED_STRING:
|
||||||
|
case TYPE_STRING:{
|
||||||
|
invalid_codepath;
|
||||||
|
}break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value_bool(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <math.h> // fmod
|
|
||||||
function Value
|
function Value
|
||||||
eval_binary(Token *pos, Token_Kind op, Value a, Value b){
|
eval_binary(Token *pos, Token_Kind op, Value a, Value b){
|
||||||
if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(a.type));
|
if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(a.type));
|
||||||
|
match_values(&a, &b);
|
||||||
|
|
||||||
// @warning: this bool path returns early, always should return untyped bool
|
if(token_is_compare(op)){
|
||||||
if(is_bool(a.type) || is_bool(b.type)){
|
return compare_values(pos, op, a, b);
|
||||||
if(!is_bool(a.type)) parsing_error(pos, "Type mismatch in binary operation %s - left: %s right: %s", name(op), docname(a.type), docname(b.type));
|
|
||||||
if(!is_bool(b.type)) parsing_error(pos, "Type mismatch in binary operation %s - left: %s right: %s", name(op), docname(a.type), docname(b.type));
|
|
||||||
|
|
||||||
Value result;
|
|
||||||
result.type = untyped_bool;
|
|
||||||
switch(op){
|
|
||||||
case TK_And: result.bool_val = a.bool_val && b.bool_val; break;
|
|
||||||
case TK_Or: result.bool_val = a.bool_val || b.bool_val; break;
|
|
||||||
case TK_GreaterThen: result.bool_val = a.bool_val > b.bool_val; break;
|
|
||||||
case TK_GreaterThenOrEqual: result.bool_val = a.bool_val >= b.bool_val; break;
|
|
||||||
case TK_LesserThen: result.bool_val = a.bool_val < b.bool_val; break;
|
|
||||||
case TK_LesserThenOrEqual: result.bool_val = a.bool_val <= b.bool_val; break;
|
|
||||||
case TK_Equals: result.bool_val = a.bool_val == b.bool_val; break;
|
|
||||||
case TK_NotEquals: result.bool_val = a.bool_val != b.bool_val; break;
|
|
||||||
invalid_default_case;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Resolved_Type *final_type = 0;
|
Value result = {};
|
||||||
Value before_conversion;
|
result.type = a.type;
|
||||||
if(is_int(a.type) && is_int(b.type)) {
|
switch(a.type->kind){
|
||||||
before_conversion.type = untyped_int;
|
case TYPE_UNTYPED_INT:
|
||||||
final_type = untyped_int;
|
case TYPE_S8:case TYPE_S16:case TYPE_S32:case TYPE_S64:
|
||||||
}
|
case TYPE_U8:case TYPE_U16:case TYPE_U32:case TYPE_U64:{
|
||||||
else{
|
switch(op){
|
||||||
before_conversion.type = untyped_float;
|
case TK_BitXor: bigint_xor(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
|
||||||
final_type = untyped_float;
|
case TK_BitAnd: bigint_and(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
|
||||||
|
case TK_BitOr: bigint_or(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
|
||||||
|
case TK_Add: bigint_add(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
|
||||||
|
case TK_Sub: bigint_sub(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
|
||||||
|
case TK_Mul: bigint_mul(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
|
||||||
|
case TK_Div: bigint_div_trunc(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
|
||||||
|
case TK_Mod: bigint_mod(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
|
||||||
|
case TK_LeftShift: bigint_shl(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
|
||||||
|
case TK_RightShift: bigint_shr(&result.big_int_val, &a.big_int_val, &b.big_int_val); break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
case TYPE_UNTYPED_BOOL:
|
||||||
|
case TYPE_BOOL:{
|
||||||
|
switch(op){
|
||||||
|
case TK_And: result.bool_val = a.bool_val && b.bool_val; break;
|
||||||
|
case TK_Or: result.bool_val = a.bool_val || b.bool_val; break;
|
||||||
|
case TK_BitAnd: result.bool_val = a.bool_val & b.bool_val; break;
|
||||||
|
case TK_BitOr: result.bool_val = a.bool_val | b.bool_val; break;
|
||||||
|
case TK_BitXor: result.bool_val = a.bool_val ^ b.bool_val; break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
case TYPE_UNTYPED_FLOAT:
|
||||||
|
case TYPE_F32: case TYPE_F64:{
|
||||||
|
switch(op){
|
||||||
|
case TK_Add: result.f64_val = a.f64_val + b.f64_val; break;
|
||||||
|
case TK_Sub: result.f64_val = a.f64_val - b.f64_val; break;
|
||||||
|
case TK_Mul: result.f64_val = a.f64_val * b.f64_val; break;
|
||||||
|
case TK_Div: result.f64_val = a.f64_val / b.f64_val; break;
|
||||||
|
invalid_default_case;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
case TYPE_UNTYPED_STRING:
|
||||||
|
case TYPE_STRING:{
|
||||||
|
invalid_codepath;
|
||||||
|
}break;
|
||||||
|
invalid_default_case;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_typed(a.type) && is_typed(b.type)){
|
|
||||||
if(a.type != b.type) parsing_error(pos, "Type mismatch in binary operation %s - left: %s right: %s", name(op), docname(a.type), docname(b.type));
|
|
||||||
else final_type = a.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(is_typed(a.type) || is_typed(b.type)){
|
|
||||||
not_implemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
S64 left_int = value_get_int(a);
|
|
||||||
S64 right_int = value_get_int(b);
|
|
||||||
F64 left_float = value_get_float(a);
|
|
||||||
F64 right_float = value_get_float(b);
|
|
||||||
|
|
||||||
assert(before_conversion.type == untyped_float || before_conversion.type == untyped_int);
|
|
||||||
// @note: for returning early with bools
|
|
||||||
Value c; c.type = untyped_bool;
|
|
||||||
switch(op){
|
|
||||||
|
|
||||||
// @note: These return early, they don't need type evaluation
|
|
||||||
// always should return untyped bool
|
|
||||||
case TK_And: {
|
|
||||||
if(final_type == untyped_int) c.bool_val = left_int && right_int;
|
|
||||||
else c.bool_val = left_float && right_float;
|
|
||||||
return c;
|
|
||||||
}break;
|
|
||||||
case TK_Or: {
|
|
||||||
if(final_type == untyped_int) c.bool_val = left_int || right_int;
|
|
||||||
else c.bool_val = left_float || right_float;
|
|
||||||
return c;
|
|
||||||
}break;
|
|
||||||
case TK_GreaterThen: {
|
|
||||||
if(final_type == untyped_int) c.bool_val = left_int > right_int;
|
|
||||||
else c.bool_val = left_float > right_float;
|
|
||||||
return c;
|
|
||||||
}break;
|
|
||||||
case TK_GreaterThenOrEqual: {
|
|
||||||
if(final_type == untyped_int) c.bool_val = left_int >= right_int;
|
|
||||||
else c.bool_val = left_float >= right_float;
|
|
||||||
return c;
|
|
||||||
}break;
|
|
||||||
case TK_LesserThen: {
|
|
||||||
if(final_type == untyped_int) c.bool_val = left_int < right_int;
|
|
||||||
else c.bool_val = left_float < right_float;
|
|
||||||
return c;
|
|
||||||
}break;
|
|
||||||
case TK_LesserThenOrEqual: {
|
|
||||||
if(final_type == untyped_int) c.bool_val = left_int <= right_int;
|
|
||||||
else c.bool_val = left_float <= right_float;
|
|
||||||
return c;
|
|
||||||
}break;
|
|
||||||
case TK_Equals: {
|
|
||||||
if(final_type == untyped_int) c.bool_val = left_int == right_int;
|
|
||||||
else c.bool_val = left_float == right_float;
|
|
||||||
return c;
|
|
||||||
}break;
|
|
||||||
case TK_NotEquals: {
|
|
||||||
if(final_type == untyped_int) c.bool_val = left_int != right_int;
|
|
||||||
else c.bool_val = left_float != right_float;
|
|
||||||
return c;
|
|
||||||
}break;
|
|
||||||
|
|
||||||
// @note: These return at the end cause need type evaluation
|
|
||||||
case TK_Add: {
|
|
||||||
left_int = left_int + right_int;
|
|
||||||
left_float = left_float + right_float;
|
|
||||||
} break;
|
|
||||||
case TK_Sub: {
|
|
||||||
left_int = left_int - right_int;
|
|
||||||
left_float = left_float - right_float;
|
|
||||||
} break;
|
|
||||||
case TK_Mul: {
|
|
||||||
left_int = left_int * right_int;
|
|
||||||
left_float = left_float * right_float;
|
|
||||||
} break;
|
|
||||||
case TK_Div: {
|
|
||||||
left_int = left_int / right_int;
|
|
||||||
left_float = left_float / right_float;
|
|
||||||
} break;
|
|
||||||
case TK_Mod: {
|
|
||||||
left_int = left_int % right_int;
|
|
||||||
left_float = fmod(left_float, right_float);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
// @WARNING: When introducing big ints & | ^ will be problematic
|
|
||||||
case TK_BitAnd: {
|
|
||||||
left_int = left_int & right_int;
|
|
||||||
if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", name(op));
|
|
||||||
} break;
|
|
||||||
case TK_BitOr: {
|
|
||||||
left_int = left_int | right_int;
|
|
||||||
if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", name(op));
|
|
||||||
} break;
|
|
||||||
case TK_BitXor: {
|
|
||||||
left_int = left_int ^ right_int;
|
|
||||||
if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", name(op));
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default: parsing_error(pos, "Binary operation %s is not allowed on types: left: %s right: %s", name(op), docname(a.type), docname(b.type));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(before_conversion.type == untyped_float){
|
|
||||||
before_conversion.f64_val = left_float;
|
|
||||||
} else {
|
|
||||||
assert(before_conversion.type == untyped_int);
|
|
||||||
before_conversion.int_val = left_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value result = convert_untyped(pos, before_conversion, final_type);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Value
|
||||||
|
eval_unary(Token *pos, Token_Kind op, Value a){
|
||||||
|
if(!is_numeric(a.type)) parsing_error(pos, "Constant application of binary %s on values of type %s is not allowed", name(op), docname(a.type));
|
||||||
|
|
||||||
|
BigInt result = {};
|
||||||
|
switch(op){
|
||||||
|
case TK_Add:{
|
||||||
|
return a;
|
||||||
|
} break;
|
||||||
|
case TK_Sub:{
|
||||||
|
if(is_int(a.type)){
|
||||||
|
bigint_negate(&result, &a.big_int_val);
|
||||||
|
return value_int(result);
|
||||||
|
} else if(is_float(a.type)){
|
||||||
|
return value_float(-a.f64_val);
|
||||||
|
} else invalid_codepath;
|
||||||
|
} break;
|
||||||
|
case TK_Neg:{
|
||||||
|
if(is_int(a.type)){
|
||||||
|
bigint_not(&result, &a.big_int_val, 64, 1); // Invalid
|
||||||
|
return value_int(result);
|
||||||
|
} else invalid_codepath;
|
||||||
|
} break;
|
||||||
|
case TK_Not:{
|
||||||
|
if(is_int(a.type)){
|
||||||
|
if(CMP_EQ == bigint_cmp_zero(&a.big_int_val)){
|
||||||
|
return value_bool(1);
|
||||||
|
} else return value_bool(0);
|
||||||
|
} else if(is_float(a.type)){
|
||||||
|
return value_bool(!a.f64_val);
|
||||||
|
} else if(is_bool(a.type)){
|
||||||
|
a.bool_val = !a.bool_val;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default: invalid_codepath;
|
||||||
|
}
|
||||||
|
invalid_return;
|
||||||
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
try_untyping(Operand *op){
|
try_untyping(Operand *op){
|
||||||
if(!op) return;
|
if(!op) return;
|
||||||
@@ -286,56 +275,6 @@ try_untyping(Operand *op){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Value
|
|
||||||
eval_unary(Token *pos, Token_Kind op, Value a){
|
|
||||||
if(!is_numeric(a.type)) parsing_error(pos, "Constant application of binary %s on values of type %s is not allowed", name(op), docname(a.type));
|
|
||||||
|
|
||||||
S64 left_int = value_get_int(a);
|
|
||||||
F64 left_float = value_get_float(a);
|
|
||||||
|
|
||||||
// @todo: bools go right through
|
|
||||||
switch(op){
|
|
||||||
case TK_Not:{
|
|
||||||
Value value;
|
|
||||||
value.type = type_bool;
|
|
||||||
value.bool_val = is_float(a.type) ? !left_float : !left_int;
|
|
||||||
return value;
|
|
||||||
}break;
|
|
||||||
case TK_Neg:{
|
|
||||||
left_int = ~left_int;
|
|
||||||
if(is_float(a.type)) type_error(pos, type_int, a.type, "[~] doesn't work on floating point");
|
|
||||||
// left_int = int_type_max(a.type) & left_int;
|
|
||||||
// @todo this doesn't work
|
|
||||||
}break;
|
|
||||||
case TK_Sub:{
|
|
||||||
left_int = -left_int;
|
|
||||||
left_float = -left_float;
|
|
||||||
}break;
|
|
||||||
case TK_Add:{
|
|
||||||
left_int = +left_int;
|
|
||||||
left_float = +left_float;
|
|
||||||
}break;
|
|
||||||
invalid_default_case;
|
|
||||||
}
|
|
||||||
// case TYPE_UINT: parsing_error(pos, "Application of unary [-] on type %s results in overflow", docname(v.type));break;
|
|
||||||
// default: parsing_error(pos, "Constant application of unary [-] on type of %s is unsupported", docname(v.type));break;
|
|
||||||
// default: parsing_error(pos, "Constant application of unary [+] on type of %s is unsupported", docname(v.type));break;
|
|
||||||
|
|
||||||
Value before_conversion;
|
|
||||||
if(is_int(a.type)){
|
|
||||||
before_conversion.type = untyped_int;
|
|
||||||
before_conversion.int_val = left_int;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
assert(is_float(a.type));
|
|
||||||
before_conversion.type = untyped_float;
|
|
||||||
before_conversion.f64_val = left_float;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value result = convert_untyped(pos, before_conversion, a.type);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define rewrite_into_const(ast,T,s) _rewrite_into_const(ast,sizeof(T),s)
|
#define rewrite_into_const(ast,T,s) _rewrite_into_const(ast,sizeof(T),s)
|
||||||
function void
|
function void
|
||||||
_rewrite_into_const(Ast *node, U64 ast_size, Value value){
|
_rewrite_into_const(Ast *node, U64 ast_size, Value value){
|
||||||
@@ -532,7 +471,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
if(type.type != type_type) parsing_error(node->pos, "Prefix array operator is only allowed on types");
|
if(type.type != type_type) parsing_error(node->pos, "Prefix array operator is only allowed on types");
|
||||||
Operand expr = require_const_int(node->expr, AST_CANT_BE_NULL);
|
Operand expr = require_const_int(node->expr, AST_CANT_BE_NULL);
|
||||||
|
|
||||||
Ast_Resolved_Type *resolved = type_array(type.type_val, expr.int_val);
|
Ast_Resolved_Type *resolved = type_array(type.type_val, bigint_as_unsigned(&expr.big_int_val));
|
||||||
sym_type(resolved, node);
|
sym_type(resolved, node);
|
||||||
return operand_type(resolved);
|
return operand_type(resolved);
|
||||||
BREAK();
|
BREAK();
|
||||||
@@ -572,7 +511,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
if(i->name) parsing_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]);
|
if(i->name) parsing_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]);
|
||||||
if(i->index){
|
if(i->index){
|
||||||
Operand index_op = require_const_int(i->index, AST_CANT_BE_NULL);
|
Operand index_op = require_const_int(i->index, AST_CANT_BE_NULL);
|
||||||
if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
U64 index = bigint_as_unsigned(&index_op.big_int_val);
|
||||||
|
if(index > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
||||||
}
|
}
|
||||||
Operand expr = resolve_expr(i->item, item_type);
|
Operand expr = resolve_expr(i->item, item_type);
|
||||||
expr.value = convert_untyped(i->pos, expr.value, item_type);
|
expr.value = convert_untyped(i->pos, expr.value, item_type);
|
||||||
@@ -895,11 +835,11 @@ resolve_const(Ast_Expr *ast, Sym *sym){
|
|||||||
For(node->members){
|
For(node->members){
|
||||||
Operand op = require_const_int(it->value, AST_CAN_BE_NULL);
|
Operand op = require_const_int(it->value, AST_CAN_BE_NULL);
|
||||||
if(op.type){
|
if(op.type){
|
||||||
value = op.int_val + 1;
|
value = bigint_as_signed(&op.big_int_val) + 1;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
op.type = type_s64;
|
op.type = type_s64;
|
||||||
op.int_val = value++;
|
bigint_init_signed(&op.big_int_val, value++);
|
||||||
}
|
}
|
||||||
|
|
||||||
sym_const(it->name, op, it, INSERT_INTO_SCOPE);
|
sym_const(it->name, op, it, INSERT_INTO_SCOPE);
|
||||||
|
|||||||
@@ -204,11 +204,10 @@ operand_type(Ast_Resolved_Type *type){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
operand_int(S64 int_val){
|
operand_int(BigInt big_int){
|
||||||
Operand result = {};
|
Operand result = {};
|
||||||
result.type = type_int;
|
result.type = type_int;
|
||||||
result.int_val = int_val;
|
bigint_init_bigint(&result.big_int_val, &big_int);
|
||||||
// result.big_int = int_val;
|
|
||||||
result.is_const = true;
|
result.is_const = true;
|
||||||
result.is_lvalue = false;
|
result.is_lvalue = false;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
Reference in New Issue
Block a user