From ddd250e7f31611bccb1516ed51121e4823151595 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sat, 9 Jul 2016 00:45:40 -0700 Subject: [PATCH] Fixed baking the right integer types into values from #ctce, added the rest of the integer type literals (10ul, etc), fixed/added struct padding/alignment in interpreter --- krakenGrammer.kgm | 6 +-- stdlib/ast_transformation.krak | 23 +++++++-- stdlib/interpreter.krak | 85 +++++++++++++++++++++----------- stdlib/string.krak | 8 +-- tests/test_ctce.expected_results | 39 +++++++++++++++ tests/test_ctce.krak | 82 ++++++++++++++++++++++++++++++ tests/tester.krak | 4 +- 7 files changed, 204 insertions(+), 43 deletions(-) diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index 9cceca1..e85810c 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -139,9 +139,8 @@ assignment_statement = factor WS "=" WS boolean_expression | factor WS "\+=" WS # 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 | "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 ; -float_end = "[0-9]+" | "[0-9]+f" | "[0-9]+d" ; +integer = "[0-9]+u?(c|s|l)?" | hexadecimal ; +floating_literal = "[0-9]+.[0-9]+(f|d)?" ; bool = "true" | "false" ; character = "'(`|[0-9]|-|=|(\\t)|[a-z]|\[|]|(\\\\)|;|(\\')|(\\n)|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|[A-Z]|{|}|\||:|\"|<|>|\?| |(\\0))'" ; @@ -149,7 +148,6 @@ keywords_also_identifiers = "obj" | "def" | "fun" | "var" | "ref" | "adt" | "cas alpha_alphanumeric = "([a-z]|[A-Z]|_)([a-z]|[A-Z]|_|[0-9])*" ; augmented_alpha_alphanumeric = alpha_alphanumeric augmented_alpha_alphanumeric | keywords_also_identifiers augmented_alpha_alphanumeric | alpha_alphanumeric | keywords_also_identifiers ; -numeric = "[0-9]+" ; # note the hacks around \things. Hmm, I feel like it actually shouldn't be like this. Added \\\* because I want to come back later string = triple_quoted_string | "\"([#-[]| |[]-~]|(\\\\)|(\\n)|(\\t)|(\\\*)|(\\0)| |[ -!]|(\\\"))*\"" ; diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 6249c13..2bf11fa 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -554,13 +554,28 @@ obj ast_transformation (Object) { break } } - if (contains_dot) - if (value_str[value_str.length()-1] == 'f') + if (contains_dot) { + if (value_str.last() == 'f') value_type = type_ptr(base_type::floating()) //value_type = type_ptr(base_type::floating()) else value_type = type_ptr(base_type::double_precision()) //value_type = type_ptr(base_type::floating()) - else - value_type = type_ptr(base_type::integer()) + } else { + var chop = 0 + if (value_str.length() > 2) { + var s = value_str.slice(-3,-1) + if (s == "uc") { chop = 2; value_type = type_ptr(base_type::ucharacter()); } + else if (s == "us") { chop = 2; value_type = type_ptr(base_type::ushort_int()); } + else if (s == "ul") { chop = 2; value_type = type_ptr(base_type::ulong_int()); } + } + if (chop == 0) { + if (value_str.last() == 'c') { chop = 1; value_type = type_ptr(base_type::character()); } + else if (value_str.last() == 's') { chop = 1; value_type = type_ptr(base_type::short_int()); } + else if (value_str.last() == 'u') { chop = 1; value_type = type_ptr(base_type::uinteger()); } + else if (value_str.last() == 'l') { chop = 1; value_type = type_ptr(base_type::long_int()); } + } + if (chop == 0) value_type = type_ptr(base_type::integer()) + value_str = value_str.slice(0, -1-chop) + } } return ast_value_ptr(value_str, value_type) } diff --git a/stdlib/interpreter.krak b/stdlib/interpreter.krak index 06c5641..39cadd8 100644 --- a/stdlib/interpreter.krak +++ b/stdlib/interpreter.krak @@ -63,6 +63,7 @@ fun raw_to_value(data:double): value fun wrap_value(val: *ast_node): value { var value_str = val->value.string_value + var value_type = val->value.value_type if (value_str[0] == '"') { // " // Comment hack for emacs now var to_ret = string() // triple quoted strings @@ -113,8 +114,18 @@ fun wrap_value(val: *ast_node): value { return value::double_precision(string_to_double(value_str.slice(0,-2))) else return value::double_precision(string_to_double(value_str)) - else - return value::integer(string_to_int(value_str)) + else { + match(value_type->base) { + base_type::character() return value::character(string_to_num(value_str)) + base_type::ucharacter() return value::ucharacter(string_to_num(value_str)) + base_type::short_int() return value::short_int(string_to_num(value_str)) + base_type::ushort_int() return value::ushort_int(string_to_num(value_str)) + base_type::integer() return value::integer(string_to_num(value_str)) + base_type::uinteger() return value::uinteger(string_to_num(value_str)) + base_type::long_int() return value::long_int(string_to_num(value_str)) + base_type::ulong_int() return value::ulong_int(string_to_num(value_str)) + } + } } error("Could not wrap value") return value::void_nothing() @@ -484,47 +495,63 @@ fun cast_value_second_half(v: value): value { } error("Illegal type to cast cast from") } -fun type_size(t: *type): ulong { +fun type_size(t: *type): ulong + return type_size_and_alignment(t).first +fun type_size_and_alignment(t: *type): pair { if (t->indirection) - return #sizeof<*void> + return make_pair(#sizeof<*void>, #sizeof<*void>) match (t->base) { base_type::object() { - var size: ulong = 0 + var total_size: ulong = 0 + var max_size: ulong = 0 + var max_align: ulong = 0 t->type_def->type_def.variables.for_each(fun(i: *ast_node) { - var individual_size = type_size(i->declaration_statement.identifier->identifier.type) - if (t->type_def->type_def.is_union) { - size = max(size, individual_size) - } else { - size += individual_size - } + var individual = type_size_and_alignment(i->declaration_statement.identifier->identifier.type) + max_size = max(max_size, individual.first) + max_align = max(max_align, individual.second) + // increase total size by the individual size + padding to get alignment + var padding = 0 + if (individual.second != 0) + padding = (individual.second - (total_size % individual.second)) % individual.second + total_size += individual.first + padding }) - return size + if (t->type_def->type_def.is_union) + total_size = max_size + // pad the end so that consecutive objects in memory are aligned + if (max_align != 0) + total_size += (max_align - (total_size % max_align)) % max_align + return make_pair(total_size, max_align) } - base_type::function() return #sizeof>> - base_type::boolean() return #sizeof - base_type::character() return #sizeof - base_type::ucharacter() return #sizeof - base_type::short_int() return #sizeof - base_type::ushort_int() return #sizeof - base_type::integer() return #sizeof - base_type::uinteger() return #sizeof - base_type::long_int() return #sizeof - base_type::ulong_int() return #sizeof - base_type::floating() return #sizeof - base_type::double_precision() return #sizeof + base_type::function() return make_pair(#sizeof>>, #sizeof<*void>) + base_type::boolean() return make_pair(#sizeof, #sizeof) + base_type::character() return make_pair(#sizeof, #sizeof) + base_type::ucharacter() return make_pair(#sizeof, #sizeof) + base_type::short_int() return make_pair(#sizeof, #sizeof) + base_type::ushort_int() return make_pair(#sizeof, #sizeof) + base_type::integer() return make_pair(#sizeof, #sizeof) + base_type::uinteger() return make_pair(#sizeof, #sizeof) + base_type::long_int() return make_pair(#sizeof, #sizeof) + base_type::ulong_int() return make_pair(#sizeof, #sizeof) + base_type::floating() return make_pair(#sizeof, #sizeof) + base_type::double_precision() return make_pair(#sizeof, #sizeof) } error(string("Invalid type for type_size: ") + t->to_string()) } fun offset_into_struct(struct_type: *type, ident: *ast_node): ulong { - var size: ulong = 0 + var offset: 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++;) + return offset + for (var i = 0; i < struct_type->type_def->type_def.variables.size; i++;) { + var size_and_align = type_size_and_alignment(struct_type->type_def->type_def.variables[i]->declaration_statement.identifier->identifier.type) + var align = size_and_align.second + if (align != 0) + offset += (align - (offset % align)) % align if (struct_type->type_def->type_def.variables[i]->declaration_statement.identifier == ident) break else - size += type_size(struct_type->type_def->type_def.variables[i]->declaration_statement.identifier->identifier.type) - return size + offset += size_and_align.first + } + return offset } // to dereference, we basically take the pointer's value (maybe going through a variable to get it) // and re-wrap it up into a variable value (so it can be assigned to, etc) diff --git a/stdlib/string.krak b/stdlib/string.krak index 65f7b30..89959b0 100644 --- a/stdlib/string.krak +++ b/stdlib/string.krak @@ -37,14 +37,14 @@ fun to_string(in: ulong): string fun to_string(in: *T): string return string("ptr:<") + to_string_num((in) cast ulong) + ">" -fun string_to_int(it: string): int { +fun string_to_num(it: string): T { var is_negative = false if (it[0] == '-') { is_negative = true it = it.slice(1,-1) } - var result = 0 - var power = 1 + var result:T = 0 + var power:T = 1 while (it.length()) { result += power * (it.last() - '0') it = it.slice(0,-2) @@ -58,7 +58,7 @@ fun string_to_double(it: string): double { var parts = it.split('.') var divisor = 1 for (var i = 0; i < parts[1].length(); i++;) divisor *= 10 - return string_to_int(parts[0]) + (string_to_int(parts[1])) cast double / divisor + return string_to_num(parts[0]) + (string_to_num(parts[1])) cast double / divisor } fun to_string_num(in: T): string { diff --git a/tests/test_ctce.expected_results b/tests/test_ctce.expected_results index db9a4b3..0979046 100644 --- a/tests/test_ctce.expected_results +++ b/tests/test_ctce.expected_results @@ -1,3 +1,8 @@ + + +=====During CTCE!===== + + 3 hello, world From Shell @@ -12,3 +17,37 @@ From Shell From Shell true true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true diff --git a/tests/test_ctce.krak b/tests/test_ctce.krak index 4b1e30c..42af371 100644 --- a/tests/test_ctce.krak +++ b/tests/test_ctce.krak @@ -3,6 +3,53 @@ import os: * import string: * import ast_nodes: * +obj first { + var p1: *char + var p2: char + var p3: int +} +obj second { + var p1: *char + var p2: char + var p3: short +} +obj third { + var p1: *char + var p2: long + var p3: char +} +obj fourth { + var p1: char + var p2: *char + var p3: long +} +obj fifth { + var p1: *char + var p2: char +} +obj sixth { + var p1: *char + var p2: char + var p3: long +} +obj seventh { + var p1: char + var p2: *char + var p3: long +} +obj eigth { + var p1: short + var p2: char +} +obj ninth { + var p1: *char + var p2: short +} +obj tenth { + var p1: char + var p2: ninth +} + fun compare_sizes() { var a = #sizeof var b = #ctce(#sizeof) @@ -22,7 +69,42 @@ fun main(): int { return it.toCharArray() }())) } + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes() + compare_sizes