diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index 29cb07e..4f0157e 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -140,7 +140,7 @@ access_operation = unarad WS "." WS identifier | unarad WS "->" WS identifier | assignment_statement = factor WS "=" WS boolean_expression | factor WS "\+=" WS boolean_expression | factor WS "-=" WS boolean_expression | factor WS "\*=" WS boolean_expression | factor WS "/=" WS boolean_expression ; # if it's being assigned to, we allow type inferencing -declaration_statement = "var" WS identifier WS "=" WS boolean_expression | "var" WS identifier WS dec_type WS "=" WS boolean_expression | "var" WS identifier WS dec_type | "var" WS identifier WS "." WS identifier WS "\(" WS opt_parameter_list WS "\)" WS dec_type ; +declaration_statement = "var" WS identifier WS "=" WS boolean_expression | "var" WS identifier WS dec_type WS "=" WS boolean_expression | "var" WS identifier WS dec_type | "ext" WS "var" WS identifier WS dec_type | "var" WS identifier WS "." WS identifier WS "\(" WS opt_parameter_list WS "\)" WS dec_type ; hexadecimal = "0x([0-9]|[a-f])+" ; integer = numeric | hexadecimal ; floating_literal = numeric "." float_end ; diff --git a/stdlib/ast_nodes.krak b/stdlib/ast_nodes.krak index bc99945..3c7dded 100644 --- a/stdlib/ast_nodes.krak +++ b/stdlib/ast_nodes.krak @@ -815,8 +815,8 @@ obj assignment_statement (Object) { return to == other.to && from == other.from } } -fun ast_declaration_statement_ptr(ident: *ast_node, expression: *ast_node): *ast_node { - var to_ret.construct(ident, expression): declaration_statement +fun ast_declaration_statement_ptr(ident: *ast_node, expression: *ast_node, is_extern: bool): *ast_node { + var to_ret.construct(ident, expression, is_extern): declaration_statement var ptr = new() ptr->copy_construct(&ast_node::declaration_statement(to_ret)) return ptr @@ -831,16 +831,19 @@ obj declaration_statement (Object) { var identifier: *ast_node var expression: *ast_node var init_method_call: *ast_node - fun construct(identifier_in: *ast_node, expression_in: *ast_node): *declaration_statement { + var is_extern: bool + fun construct(identifier_in: *ast_node, expression_in: *ast_node, is_extern_in: bool): *declaration_statement { identifier = identifier_in expression = expression_in init_method_call = null() + is_extern = is_extern_in return this } fun copy_construct(old: *declaration_statement) { identifier = old->identifier expression = old->expression init_method_call = old->init_method_call + is_extern = old->is_extern } fun destruct() { } @@ -849,7 +852,7 @@ obj declaration_statement (Object) { copy_construct(&other) } fun operator==(other: ref declaration_statement): bool { - return identifier == other.identifier && expression == other.expression && init_method_call == other.init_method_call + return identifier == other.identifier && expression == other.expression && init_method_call == other.init_method_call && is_extern == other.is_extern } } fun ast_if_comp_ptr(): *ast_node { diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index a7bc45b..4d706b8 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -620,7 +620,7 @@ obj ast_transformation (Object) { } if (!identifier->identifier.type) error(node, "declaration statement with no type or expression from which to inference type") if (identifier->identifier.type->is_none() || (identifier->identifier.type->indirection == 0 && identifier->identifier.type->is_void())) error(node, "declaration statement with bad type") - var declaration = ast_declaration_statement_ptr(identifier, expression) + var declaration = ast_declaration_statement_ptr(identifier, expression, get_node("\"ext\"", node) != null>()) // ok, deal with the possible init position method call if (identifiers.size == 2) { var parameters = get_nodes("parameter", node).map(fun(child: *tree): *ast_node return transform(get_node("boolean_expression", child), scope, template_replacements);) diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index b670e97..904e61f 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -463,7 +463,7 @@ obj c_generator (Object) { vert->adt_def.options.for_each(fun(option: *ast_node) { add_to_enum += string("enum_opt_") + get_name(option) + "," if (!option->identifier.type->is_empty_adt_option()) - add_to_structs += generate_declaration_statement(ast_declaration_statement_ptr(option, null()), null(), null(), null>>>(), false).one_string() + ";\n" + add_to_structs += generate_declaration_statement(ast_declaration_statement_ptr(option, null(), false), null(), null(), null>>>(), false).one_string() + ";\n" }) structs += string("enum { ") + add_to_enum + " } flag;\n" structs += string("union { ") + add_to_structs + " } data;\n" @@ -533,7 +533,10 @@ obj c_generator (Object) { var ident_type = identifier->identifier.type // we do the declaration in the pre now so that we can take it's address to close over it for things like recursive closures // we only make it first if it's a function type though, so that global levels still work - var to_ret = code_triple(type_to_c(identifier->identifier.type) + " " + get_name(identifier), string(), string()) + var pre_stuff = type_to_c(identifier->identifier.type) + " " + get_name(identifier) + if (node->declaration_statement.is_extern) + pre_stuff = string("extern ") + pre_stuff + var to_ret = code_triple(pre_stuff, string(), string()) if (node->declaration_statement.expression) { if (ident_type->indirection == 0 && (ident_type->is_adt() || (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(node->declaration_statement.expression)->clone_with_increased_indirection()))))) { to_ret.pre += ";\n" @@ -629,7 +632,7 @@ obj c_generator (Object) { if (function_return_type->is_ref) temp_ident_type = temp_ident_type->clone_with_increased_indirection() var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), temp_ident_type, null()) - var declaration = ast_declaration_statement_ptr(temp_ident, null()) + var declaration = ast_declaration_statement_ptr(temp_ident, null(), false) // have to pass false to the declaration generator, so can't do it through generate_statement to_ret.pre = generate_declaration_statement(declaration, enclosing_object, enclosing_func, defer_stack, false).one_string() + ";\n" if ((function_return_type->is_object() || return_value_type->is_object()) && !function_return_type->equality(return_value_type, false)) @@ -697,7 +700,7 @@ obj c_generator (Object) { var option_str = generate(case_node->case_statement.option, enclosing_object, enclosing_func, defer_stack, false).one_string() var to_ret_case = code_triple("/*case ") + option_str + "*/ if(" + matching_value.value + ".flag == " + string("enum_opt_") + option_str + ") {\n" if (case_node->case_statement.unpack_ident) { - to_ret_case += generate_declaration_statement(ast_declaration_statement_ptr(case_node->case_statement.unpack_ident, null()), null(), null(), null>>>(), false).one_string() + to_ret_case += generate_declaration_statement(ast_declaration_statement_ptr(case_node->case_statement.unpack_ident, null(), false), null(), null(), null>>>(), false).one_string() to_ret_case += string(" = ") + matching_value.value + ".data." + option_str + ";\n" } else { to_ret_case += "/*no unpack_ident*/\n" @@ -734,7 +737,7 @@ obj c_generator (Object) { } if (need_variable) { var temp_ident = ast_identifier_ptr(string("temporary_value")+get_id(), get_ast_type(node), null()) - var declaration = ast_declaration_statement_ptr(temp_ident, null()) + var declaration = ast_declaration_statement_ptr(temp_ident, null(), false) // have to pass false to the declaration generator, so can't do it through generate_statement var trip_ret = code_triple() // trip_ret.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null>>>(), false).one_string() + " = " + to_ret + ";\n" @@ -877,7 +880,7 @@ obj c_generator (Object) { var param_type = get_ast_type(param) if (!in_function_param_type->is_ref && param_type->indirection == 0 && (param_type->is_adt() || (param_type->is_object() && has_method(param_type->type_def, "copy_construct", vector(param_type->clone_with_indirection(1)))))) { var temp_ident = ast_identifier_ptr(string("temporary_param")+get_id(), param_type->clone_without_ref(), null()) - var declaration = ast_declaration_statement_ptr(temp_ident, null()) + var declaration = ast_declaration_statement_ptr(temp_ident, null(), false) // have to pass false to the declaration generator, so can't do it through generate_statement call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null>>>(), false).one_string() + ";\n" call_string.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(param))))), enclosing_object, enclosing_func, null>>>()).one_string() @@ -892,7 +895,7 @@ obj c_generator (Object) { if (!func_return_type->is_ref && (needs_temp_for_destruct || (!func_return_type->is_void() && need_variable)) ) { // kind of ugly combo here of var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_type, null()) - var declaration = ast_declaration_statement_ptr(temp_ident, null()) + var declaration = ast_declaration_statement_ptr(temp_ident, null(), false) // have to pass false to the declaration generator, so can't do it through generate_statement call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null>>>(), false).one_string() + ";\n" pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string() @@ -913,7 +916,7 @@ obj c_generator (Object) { // lambda if (pre_call == "" && (!func_return_type->is_void() || func_return_type->indirection)) { var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_type, null()) - var declaration = ast_declaration_statement_ptr(temp_ident, null()) + var declaration = ast_declaration_statement_ptr(temp_ident, null(), false) // have to pass false to the declaration generator, so can't do it through generate_statement call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null>>>(), false).one_string() + ";\n" pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string() diff --git a/stdlib/io.krak b/stdlib/io.krak index 80f07e9..82fd588 100644 --- a/stdlib/io.krak +++ b/stdlib/io.krak @@ -2,43 +2,56 @@ import string; import vector; import mem:* -fun println() : void { - print("\n"); +ext fun printf(fmt_str: *char, ...): int +ext fun fprintf(file: *void, format: *char, ...): int +ext fun snprintf(to_str: *char, num: ulong, format: *char, ...): int +ext fun fflush(file: int): int +ext var stderr: *void + +fun printlnerr(toPrint: T) : void { + printerr(toPrint) + printerr("\n") +} +fun printerr(toPrint: string::string) : void { + var charArr = toPrint.toCharArray() + printerr(charArr) + delete(charArr) +} +fun printerr(toPrint: *char) : void { + fprintf(stderr, "%s", toPrint) + fflush(0) } fun println(toPrint: T) : void { print(toPrint) print("\n") } - -fun print(toPrint: *T) - print((toPrint) cast ulong) - -ext fun printf(fmt_str: *char, ...): int -ext fun fflush(file: int): int fun print(toPrint: *char) : void { printf("%s", toPrint) fflush(0) } +fun println() + print("\n") +fun print(toPrint: *T) { + print("ptr:<") + print((toPrint) cast ulong) + print(">") +} fun print(toPrint: char) : void print(string::string(toPrint)) fun print(toPrint: string::string) : void { var charArr = toPrint.toCharArray() - defer delete(charArr) - print(charArr); + print(charArr) + delete(charArr) } - -fun print(toPrint: bool): void { +fun print(toPrint: bool) { if (toPrint) print("true") else print("false") - return; } - -ext fun snprintf(to_str: *char, num: ulong, format: *char, ...): int fun print(toPrint: float) print((toPrint) cast double) @@ -55,7 +68,7 @@ fun print(toPrint: T): void // Ok, just some DEAD simple file io for now ext fun fopen(path: *char, mode: *char): *void ext fun fclose(file: *void): int -ext fun fprintf(file: *void, format: *char, ...): int +// fprintf is already used for stderr above ext fun ftell(file: *void): long ext fun fseek(file: *void, offset: long, whence: int): int ext fun fread(ptr: *void, size: ulong, nmemb: ulong, file: *void): ulong