From 12dfa837e31bf09adb1335219473b9a7e6db9eac Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sun, 22 May 2016 13:08:10 -0700 Subject: [PATCH] Added in extern global variables and printing of *char and string to stderr with printlnerr, printerr. Note that this will still compile in a previous version, but instead of extern, stderr will be newly declared. This is ok, because this version of the compiler never uses it, so we'll only use it after this one is bootstrapped in. --- krakenGrammer.kgm | 2 +- stdlib/ast_nodes.krak | 11 ++++++--- stdlib/ast_transformation.krak | 2 +- stdlib/c_generator.krak | 19 ++++++++------ stdlib/io.krak | 45 ++++++++++++++++++++++------------ 5 files changed, 49 insertions(+), 30 deletions(-) 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