diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index c2d3bfc..2ce4eb2 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -7,6 +7,8 @@ import util:* import tree:* import symbol:* import ast_nodes:* +// for error with syntax tree +import ast_transformation:* import poset:* fun code_triple(): code_triple return code_triple(string(), string(), string()); @@ -464,6 +466,9 @@ obj c_generator (Object) { var function_return_type = get_ast_type(enclosing_func)->return_type var to_ret = code_triple() + if (!function_return_type->is_void() && !function_return_type->equality(get_ast_type(return_value), false)) + error(ast_to_syntax[node], "return value type does not match function return type") + to_ret += "return" var refamp = string() if (function_return_type->is_ref) diff --git a/stdlib/interpreter.krak b/stdlib/interpreter.krak index 994e402..2d677fb 100644 --- a/stdlib/interpreter.krak +++ b/stdlib/interpreter.krak @@ -80,6 +80,9 @@ fun wrap_value(val: *ast_node): value { } else if (value_str[i] == '\\' && value_str[i+1] == 't') { to_ret += '\t' i++ + } else if (value_str[i] == '\\' && value_str[i+1] == '\\') { + to_ret += '\\' + i++ } else if (i == value_str.length()-2) { to_ret += value_str[i] to_ret += value_str[i+1] @@ -189,6 +192,15 @@ fun do_basic_op(func_name: string, a: value, b: value): value { value::floating(av) return do_basic_floating_op_second_half(func_name, av, b, null()) value::double_precision(av) return do_basic_floating_op_second_half(func_name, av, b, null()) value::pointer(av) { + var real_b = get_real_value(b) + if (func_name == "==") { + if (!is_pointer(real_b)) { + print("equality between pointer and not pointer: ") + print_value(real_b) + error(":/") + } + return value::boolean(av.first == real_b.pointer.first) + } var inc_in_bytes = cast_value(b, type_ptr(base_type::ulong_int())).ulong_int * type_size(av.second->clone_with_decreased_indirection()) var ptr = null() if (func_name == "+") { @@ -196,7 +208,9 @@ fun do_basic_op(func_name: string, a: value, b: value): value { } else if (func_name == "-") { ptr = ((av.first) cast *char - inc_in_bytes) cast *void } else { - error("pointer arithmatic is not + or -") + println(string("pointer arithmatic is not + or -: ") + func_name + ", b is: ") + print_value(b) + error(string("pointer arithmatic is not + or -: ") + func_name) } return value::pointer(make_pair(ptr, av.second)) } @@ -486,9 +500,9 @@ fun type_size(t: *type): ulong { error(string("Invalid type for type_size: ") + t->to_string()) } fun offset_into_struct(struct_type: *type, ident: *ast_node): ulong { - if (struct_type->type_def->type_def.is_union) - return 0 var size: ulong = 0 + if (struct_type->type_def->type_def.is_union) + return size for (var i = 0; i < struct_type->type_def->type_def.variables.size; i++;) if (struct_type->type_def->type_def.variables[i]->declaration_statement.identifier == ident) break @@ -496,6 +510,8 @@ fun offset_into_struct(struct_type: *type, ident: *ast_node): ulong { size += type_size(struct_type->type_def->type_def.variables[i]->declaration_statement.identifier->identifier.type) return size } +fun dereference_pointer_into_variable(dereference_val: value): value + return value::variable(make_pair(get_real_value(dereference_val).pointer.first, dereference_val.pointer.second->clone_with_decreased_indirection())) fun pop_and_free(var_stack: *stack>) { var_stack->pop().for_each(fun(k: *ast_node, v: value) { match(v) { @@ -595,6 +611,12 @@ obj interpreter (Object) { var func_value = get_real_value(interpret(func_call_func, var_stack, enclosing_object, enclosing_func).first) func_call_func = func_value.function.first possible_closure_map = *func_value.function.second + // if the closure closes over this, put it as the enclosing object inside the closure + possible_closure_map.for_each(fun(key: *ast_node, v: value) { + if (key->identifier.name == "this") { + new_enclosing_object = get_real_value(dereference_pointer_into_variable(v)) + } + }) /*println("possible_closure_map is")*/ /*possible_closure_map.for_each(fun(key: *ast_node, v: value) print(get_ast_name(key) + " ");)*/ /*println()*/ @@ -674,7 +696,7 @@ obj interpreter (Object) { dereference_val = do_basic_op(string("+"), parameters[0], parameters[1]) if (!is_pointer(get_real_value(parameters[0]))) error("Trying to take dereference not a pointer") - return make_pair(value::variable(make_pair(get_real_value(dereference_val).pointer.first, dereference_val.pointer.second->clone_with_decreased_indirection())), control_flow::nor()) + return make_pair(dereference_pointer_into_variable(dereference_val), control_flow::nor()) } // check for built-in-ish externs (everything the standard library needs) if (func_name == "printf" || func_name == "malloc" || func_name == "free" || func_name == "memmove" || func_name == "fflush" || func_name == "snprintf" || func_name == "fopen" || func_name == "fclose" || func_name == "ftell" || func_name == "fseek" || func_name == "fread" || func_name == "fwrite" || func_name == "atan" || func_name == "atan2" || func_name == "acos" || func_name == "asin" || func_name == "tan" || func_name == "cos" || func_name == "sin") @@ -981,12 +1003,22 @@ obj interpreter (Object) { // check for global if (globals.contains_key(ident)) return make_pair(globals[ident], control_flow::nor()) - println("couldn't find it in interpret identifier") + println("couldn't find it in interpret identifier, scope:") for (var i = 0; i < var_stack->size(); i++;) { println(string("level: ") + i) var_stack->from_top(i).for_each(fun(key: *ast_node, v: value) print(get_ast_name(key) + " ");) println() } + if (is_object_like(enclosing_object)) { + println("object scope:") + var object_def = enclosing_object.object_like.second->type_def + for (var i = 0; i < object_def->type_def.variables.size; i++;) { + print(get_ast_name(object_def->type_def.variables[i]) + " ") + } + } else { + print("no object scope: ") + print_value(enclosing_object) + } error(string("Cannot find variable: ") + ident->identifier.name) } fun interpret_cast(node: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node): pair { diff --git a/stdlib/obj_lower.krak b/stdlib/obj_lower.krak index 6a0e515..559032c 100644 --- a/stdlib/obj_lower.krak +++ b/stdlib/obj_lower.krak @@ -170,7 +170,12 @@ fun obj_lower(name_ast_map: *map,*ast_node>>, ast_to_ return; if (!ident_type->is_ref && ident_type->indirection == 0 && ident_type->is_object()) { if (backing.expression && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(backing.expression)->clone_with_increased_indirection()))) { - add_after_in(ast_statement_ptr(make_method_call(backing.identifier, "copy_construct", vector(make_operator_call("&", vector(backing.expression))))), + var temp_cpy_ctst = ast_identifier_ptr("temp_declaration_copy_construct", get_ast_type(backing.expression)->clone_without_ref(), null()) + var declaration = ast_statement_ptr(ast_declaration_statement_ptr(temp_cpy_ctst, backing.expression, false)) + add_after_in(ast_statement_ptr(make_method_call(backing.identifier, "copy_construct", vector(make_operator_call("&", vector(temp_cpy_ctst))))), + parent_chain->top(), parent_chain->from_top(1)) + // do second so the order's right + add_after_in(declaration, parent_chain->top(), parent_chain->from_top(1)) backing.expression = null() } diff --git a/stdlib/regex.krak b/stdlib/regex.krak index 558229e..2e2adab 100644 --- a/stdlib/regex.krak +++ b/stdlib/regex.krak @@ -1,6 +1,6 @@ import io import string -import ast_transformation +import util import vector import string import mem @@ -151,7 +151,7 @@ obj regex (Object, Serializable) { var perenEnd = i + 1 for (var depth = 1; depth > 0; perenEnd++;) { if (perenEnd >= regex_string.length()) - ast_transformation::error(string::string("can't find matching peren in: ") + regex_string) + util::error(string::string("can't find matching peren in: ") + regex_string) // be careful, this isn't quite right yet /*var not_non_special = perenEnd == 0 || (regex_string[perenEnd-1] != '\\' && regex_string[perenEnd-1] != '[' && (perenEnd+1 >= regex_string.length() || regex_string[perenEnd+1] != ']'))*/ var not_non_special = perenEnd == 0 || (regex_string[perenEnd-1] != '[' && (perenEnd+1 >= regex_string.length() || regex_string[perenEnd+1] != ']')) diff --git a/stdlib/util.krak b/stdlib/util.krak index a59318e..d3e0a74 100644 --- a/stdlib/util.krak +++ b/stdlib/util.krak @@ -41,18 +41,18 @@ fun min(a: T, b: T): T { fun hash(item: T): ulong return item.hash() fun hash(item: *T): ulong return (item) cast ulong -fun hash(item: char): ulong return item -fun hash(item: uchar): ulong return item -fun hash(item: short): ulong return item -fun hash(item: ushort): ulong return item -fun hash(item: int): ulong return item -fun hash(item: uint): ulong return item -fun hash(item: long): ulong return item -fun hash(item: ulong): ulong return item +fun hash(item: char): ulong return (item) cast ulong +fun hash(item: uchar): ulong return (item) cast ulong +fun hash(item: short): ulong return (item) cast ulong +fun hash(item: ushort): ulong return (item) cast ulong +fun hash(item: int): ulong return (item) cast ulong +fun hash(item: uint): ulong return (item) cast ulong +fun hash(item: long): ulong return (item) cast ulong +fun hash(item: ulong): ulong return (item) cast ulong // default hash fun hash(item: T): ulong { io::println("using empty hash - please do not do!") - return 0 + return (0) cast ulong } fun make_pair(first: T, second: U): pair { diff --git a/tests/test_map.expected_results b/tests/test_map.expected_results index 33c0d3f..377591a 100644 --- a/tests/test_map.expected_results +++ b/tests/test_map.expected_results @@ -1,3 +1,4 @@ +Test linear map: 3 2 1 @@ -10,6 +11,7 @@ Lookie, a map! What I get for not testing different types key: 7, value: Lookie, a map! key: 30, value: we'll look for for_each too +Test hash map: 3 2 1 diff --git a/tests/test_map.krak b/tests/test_map.krak index 11cb0b4..32f0f0f 100644 --- a/tests/test_map.krak +++ b/tests/test_map.krak @@ -24,9 +24,11 @@ fun test_map(m: ref T, mapEx: ref V) { mapEx.for_each(fun(key:int, value:*char) { print("key: "); print(key); print(", value: "); println(value); }) } fun main(): int { + println("Test linear map:") var m1 = map(3,1) var mapEx1 = map(7, "Lookie, a map!") test_map(m1, mapEx1) + println("Test hash map:") var m2 = hash_map(3,1) var mapEx2 = hash_map(7, "Lookie, a map!") test_map(m2, mapEx2)