use package core.intrinsics.wasm {
sqrt_f32, sqrt_f64,
- abs_f32, abs_f64
+ abs_f32, abs_f64,
+ copysign_f32, copysign_f64
}
+E :: 2.71828182845904523536f;
PI :: 3.14159265f;
TAU :: 6.28318330f;
sqrt_i64 :: proc (x: i64) -> i64 do return ~~sqrt_f64(~~x);
sqrt :: proc { sqrt_f32, sqrt_f64, sqrt_i32, sqrt_i64 }
+copysign :: proc { copysign_f32, copysign_f64 }
+
abs_i32 :: proc (x: i32) -> i32 {
if x >= 0 do return x;
return -x;
abs :: proc { abs_i32, abs_i64, abs_f32, abs_f64 }
pow_int :: proc (base: $T, p: i32) -> T {
- if base == 0 && p == 0 do return 1;
- elseif p == 0 do return 1;
+ if base == 0 do return 0;
+ if p == 0 do return 1;
+
a := 1;
- b := p;
- c := base;
- while b > 0 {
- if b % 2 == 1 do a *= c;
- b = b >> 1;
- c *= c;
+ while p > 0 {
+ if p % 2 == 1 do a *= base;
+ p = p >> 1;
+ base *= base;
}
+
return a;
}
-pow_float :: proc (base: $T, p: f32) -> T {
- if base == 0 && p == 0 do return 1;
- elseif p == 0 do return 1;
+pow_float :: proc (base: $T, p: T) -> T {
+ if p >= 1 {
+ tmp := pow_float(p = p / 2, base = base);
+ return tmp * tmp;
+ }
+
+ low : T = 0;
+ high : T = 1;
+
+ sqr := sqrt(base);
+ acc := sqr;
+ mid := high / 2;
+
+ while abs(mid - p) > 0.00001 {
+ sqr = sqrt(sqr);
+
+ if mid <= p {
+ low = mid;
+ acc *= sqr;
+ } else {
+ high = mid;
+ acc /= sqr;
+ }
+
+ mid = (low + high) / 2;
+ }
+ return acc;
}
pow :: proc { pow_int, pow_float }
+exp :: proc (p: $T) -> T do return pow(base = cast(T) E, p = p);
ln :: proc (a: f32) -> f32 {
static AstStructType* parse_struct(OnyxParser* parser);
static void parse_function_params(OnyxParser* parser, AstFunction* func);
static b32 parse_possible_directive(OnyxParser* parser, const char* dir);
-static AstFunction* parse_function_definition(OnyxParser* parser);
+static b32 parse_possible_function_definition(OnyxParser* parser, AstTyped** ret);
+static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* token);
static AstTyped* parse_global_declaration(OnyxParser* parser);
static AstEnumType* parse_enum_declaration(OnyxParser* parser);
static AstTyped* parse_top_level_expression(OnyxParser* parser);
}
}
+static OnyxToken* find_matching_paren(OnyxToken* paren) {
+ TokenType match = 0;
+ switch ((u16) paren->type) {
+ case '(': match = ')'; break;
+ case '[': match = ']'; break;
+ case '{': match = '}'; break;
+ case '<': match = '>'; break;
+ default: return NULL;
+ }
+
+ i32 paren_count = 1;
+ i32 i = 1;
+ while (paren_count > 0) {
+ TokenType type = (paren + i)->type;
+ if (type == Token_Type_End_Stream) return NULL;
+
+ if (type == paren->type) paren_count++;
+ else if (type == match) paren_count--;
+
+ i++;
+ }
+
+ return paren + (i - 1);
+}
+
// Advances to next token no matter what
static OnyxToken* expect_token(OnyxParser* parser, TokenType token_type) {
if (parser->hit_unexpected_token) return NULL;
switch ((u16) parser->curr->type) {
case '(': {
+ if (parse_possible_function_definition(parser, &retval)) {
+ // CLEANUP
+ add_node_to_process(parser, (AstNode *) retval);
+ break;
+ }
+
consume_token(parser);
AstTyped* expr = parse_compound_expression(parser, 0);
expect_token(parser, ')');
}
case Token_Type_Keyword_Proc: {
- retval = (AstTyped *) parse_function_definition(parser);
+ OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc);
+ retval = (AstTyped *) parse_function_definition(parser, proc_token);
retval->flags |= Ast_Flag_Function_Used;
// TODO: Maybe move this somewhere else?
}
static BinaryOp binary_op_from_token_type(TokenType t) {
- switch (t) {
+ switch ((u16) t) {
case Token_Type_Equal_Equal: return Binary_Op_Equal;
case Token_Type_Not_Equal: return Binary_Op_Not_Equal;
case Token_Type_Less_Equal: return Binary_Op_Less_Equal;
}
// 'proc' <func_params> ('->' <type>)? <directive>* <block>
-static AstFunction* parse_function_definition(OnyxParser* parser) {
- OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc);
-
+static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* token) {
if (parser->curr->type == '{') {
AstOverloadedFunction* ofunc = make_node(AstOverloadedFunction, Ast_Kind_Overloaded_Function);
- ofunc->token = proc_token;
+ ofunc->token = token;
bh_arr_new(global_heap_allocator, ofunc->overloads, 4);
}
AstFunction* func_def = make_node(AstFunction, Ast_Kind_Function);
- func_def->token = proc_token;
+ func_def->token = token;
func_def->operator_overload = -1;
bh_arr_new(global_heap_allocator, func_def->allocate_exprs, 4);
}
}
+static b32 parse_possible_function_definition(OnyxParser* parser, AstTyped** ret) {
+ if (parser->curr->type == Token_Type_Keyword_Proc) {
+ OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc);
+ AstFunction* func_node = parse_function_definition(parser, proc_token);
+ *ret = (AstTyped *) func_node;
+ return 1;
+ }
+
+ if (parser->curr->type == '(') {
+ OnyxToken* matching_paren = find_matching_paren(parser->curr);
+ if (matching_paren == NULL) return 0;
+
+ OnyxToken* token_after_paren = matching_paren + 1;
+ if (token_after_paren->type != Token_Type_Right_Arrow
+ && token_after_paren->type != '{'
+ && token_after_paren->type != Token_Type_Keyword_Do
+ && token_after_paren->type != Token_Type_Empty_Block)
+ return 0;
+
+ b32 hit_colon = 0;
+ OnyxToken* tmp_token = parser->curr;
+ while (tmp_token < matching_paren) {
+ if (tmp_token->type == ':') {
+ hit_colon = 1;
+ break;
+ }
+
+ tmp_token++;
+ }
+
+ if (!hit_colon) return 0;
+
+ OnyxToken* proc_token = parser->curr;
+ AstFunction* func_node = parse_function_definition(parser, proc_token);
+ *ret = (AstTyped *) func_node;
+ return 1;
+ }
+
+ return 0;
+}
+
// 'global' <type>
static AstTyped* parse_global_declaration(OnyxParser* parser) {
AstGlobal* global_node = make_node(AstGlobal, Ast_Kind_Global);
// <expr>
static AstTyped* parse_top_level_expression(OnyxParser* parser) {
if (parser->curr->type == Token_Type_Keyword_Proc) {
- AstFunction* func_node = parse_function_definition(parser);
+ OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc);
+ AstFunction* func_node = parse_function_definition(parser, proc_token);
add_node_to_process(parser, (AstNode *) func_node);