diff --git a/source/toy_attributes.c b/source/toy_attributes.c index 8f30995..bca3d27 100644 --- a/source/toy_attributes.c +++ b/source/toy_attributes.c @@ -37,6 +37,8 @@ Toy_Value Toy_private_handleStringAttributes(Toy_VM* vm, Toy_Value compound, Toy free(buffer); return TOY_VALUE_FROM_STRING(str); } + //TODO: as capitalized + //TODO: split? else { char buffer[256]; snprintf(buffer, 256, "Unknown attribute '%s' of type '%s'", TOY_VALUE_AS_STRING(attribute)->leaf.data, Toy_getValueTypeAsCString(compound.type)); diff --git a/source/toy_attributes.h b/source/toy_attributes.h index 1e6811d..e665eb5 100644 --- a/source/toy_attributes.h +++ b/source/toy_attributes.h @@ -11,13 +11,11 @@ // [x] array.length // [x] array.pushBack(x) // [x] array.popBack() -// [x] array.forEach(fn) // fn(x) -> void // [ ] array.sort(fn) // fn(a,b) -> int // [x] table.length // [x] table.insert(x, y) // [x] table.hasKey(x) // [x] table.remove(x) -// [ ] table.forEach(fn) // fn(x,y) -> void Toy_Value Toy_private_handleStringAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute); Toy_Value Toy_private_handleArrayAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute); diff --git a/source/toy_parser.c b/source/toy_parser.c index 20d7450..3e81546 100644 --- a/source/toy_parser.c +++ b/source/toy_parser.c @@ -198,7 +198,7 @@ static ParsingTuple parsingRulesetTable[] = { //structural operators {PREC_CALL,group,invoke},// TOY_TOKEN_OPERATOR_PAREN_LEFT, {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_PAREN_RIGHT, - {PREC_GROUP,compound,aggregate},// TOY_TOKEN_OPERATOR_BRACKET_LEFT, + {PREC_CALL,compound,aggregate},// TOY_TOKEN_OPERATOR_BRACKET_LEFT, {PREC_NONE,compound,aggregate},// TOY_TOKEN_OPERATOR_BRACKET_RIGHT, {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACE_LEFT, {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACE_RIGHT, diff --git a/source/toy_vm.c b/source/toy_vm.c index 6bbee08..44ed9dd 100644 --- a/source/toy_vm.c +++ b/source/toy_vm.c @@ -895,6 +895,8 @@ static void processConcat(Toy_VM* vm) { static void processIndex(Toy_VM* vm) { unsigned char count = READ_BYTE(vm); //value[index, length] ; 1[2, 3] + //TODO: slicing from the end of a string/array, value[0:-1] + Toy_Value value = TOY_VALUE_FROM_NULL(); Toy_Value index = TOY_VALUE_FROM_NULL(); Toy_Value length = TOY_VALUE_FROM_NULL(); diff --git a/tests/scripts/test_algo_fibonacci.toy b/tests/scripts/algorithms/test_fibonacci.toy similarity index 100% rename from tests/scripts/test_algo_fibonacci.toy rename to tests/scripts/algorithms/test_fibonacci.toy diff --git a/tests/scripts/algorithms/test_rule_110.toy b/tests/scripts/algorithms/test_rule_110.toy new file mode 100644 index 0000000..2eae083 --- /dev/null +++ b/tests/scripts/algorithms/test_rule_110.toy @@ -0,0 +1 @@ +//WARN: not yet implemented \ No newline at end of file diff --git a/tests/scripts/test_variables.toy b/tests/scripts/basics/test_logical_operators.toy similarity index 99% rename from tests/scripts/test_variables.toy rename to tests/scripts/basics/test_logical_operators.toy index d20f270..b255474 100644 --- a/tests/scripts/test_variables.toy +++ b/tests/scripts/basics/test_logical_operators.toy @@ -163,5 +163,3 @@ print !false; //true var i = 42; print a; } - -//TODO: type casting \ No newline at end of file diff --git a/tests/scripts/test_scopes.toy b/tests/scripts/basics/test_scope_resolution.toy similarity index 100% rename from tests/scripts/test_scopes.toy rename to tests/scripts/basics/test_scope_resolution.toy diff --git a/tests/scripts/test_source_empty.toy b/tests/scripts/basics/test_source_empty_file.toy similarity index 100% rename from tests/scripts/test_source_empty.toy rename to tests/scripts/basics/test_source_empty_file.toy diff --git a/tests/scripts/test_source_empty_with_comments.toy b/tests/scripts/basics/test_source_empty_file_with_comment.toy similarity index 100% rename from tests/scripts/test_source_empty_with_comments.toy rename to tests/scripts/basics/test_source_empty_file_with_comment.toy diff --git a/tests/scripts/basics/test_truthiness.toy b/tests/scripts/basics/test_truthiness.toy new file mode 100644 index 0000000..e750146 --- /dev/null +++ b/tests/scripts/basics/test_truthiness.toy @@ -0,0 +1,90 @@ +//NOTE: Not tested: null (neither true or false), Opaque, Any +{ + //booleans + var value: Bool = true; + if (value) print "boolean"; + else assert false, "boolean"; +} + +{ + var value: Bool = false; + if (value) assert false, "boolean"; + else print "boolean"; +} + +//integers +{ + var value: Int = 42; + if (value) print "integer"; + else assert false, "integer"; +} + +{ + var value: Int = 0; + if (value) assert false, "integer"; + else print "integer"; +} + +//floats +{ + var value: Float = 42.8891; + if (value) print "float"; + else assert false, "float"; +} + +{ + var value: Float = 0; + if (value) assert false, "float"; + else print "float"; +} + +//strings +{ + var value: String = "foobar"; + if (value) print "string"; + else assert false, "string"; +} + +{ + var value: String = ""; //empty string is truthy + if (value) print "string"; + else assert false, "string"; +} + +//arrays +{ + var value: Array = [1,2,3]; + if (value) print "array"; + else assert false, "array"; +} + +{ + var value: Array = []; //empty array is truthy + if (value) print "array"; + else assert false, "array"; +} + +//table +{ + var value: Table = ["alpha":"bravo"]; + if (value) print "table"; + else assert false, "table"; +} + +{ + var value: Table = [:]; //empty table is truthy + if (value) print "table"; + else assert false, "table"; +} + +//function +{ + fn identity(x) { + return x; + } + + if (identity) print "function"; + else assert false, "function"; +} + +//TODO: test library as API, would be cleaner than using asserts \ No newline at end of file diff --git a/tests/scripts/test_type_names.toy b/tests/scripts/basics/test_typenames.toy similarity index 79% rename from tests/scripts/test_type_names.toy rename to tests/scripts/basics/test_typenames.toy index df64701..7bb0853 100644 --- a/tests/scripts/test_type_names.toy +++ b/tests/scripts/basics/test_typenames.toy @@ -1,4 +1,4 @@ -//typenames are now capitalized, so ensure they don't overlap with variable names +//NOTE: typenames are now capitalized, to ensure they don't overlap with variable names var bool: Bool = true; print bool; diff --git a/tests/scripts/test_keyword_assert.toy b/tests/scripts/keywords/test_keyword_assert.toy similarity index 100% rename from tests/scripts/test_keyword_assert.toy rename to tests/scripts/keywords/test_keyword_assert.toy diff --git a/tests/scripts/test_keyword_for_iteration.toy b/tests/scripts/keywords/test_keyword_for_iteration.toy similarity index 74% rename from tests/scripts/test_keyword_for_iteration.toy rename to tests/scripts/keywords/test_keyword_for_iteration.toy index 04476a4..33b64db 100644 --- a/tests/scripts/test_keyword_for_iteration.toy +++ b/tests/scripts/keywords/test_keyword_for_iteration.toy @@ -1,4 +1,4 @@ -//URGENT: empty test script +//WARN: empty test script //TODO: test iteration on arrays, tables, closures diff --git a/tests/scripts/test_keyword_if_then_else.toy b/tests/scripts/keywords/test_keyword_if_then_else.toy similarity index 100% rename from tests/scripts/test_keyword_if_then_else.toy rename to tests/scripts/keywords/test_keyword_if_then_else.toy diff --git a/tests/scripts/test_keyword_if_then_else_no_braces.toy b/tests/scripts/keywords/test_keyword_if_then_else_no_braces.toy similarity index 100% rename from tests/scripts/test_keyword_if_then_else_no_braces.toy rename to tests/scripts/keywords/test_keyword_if_then_else_no_braces.toy diff --git a/tests/scripts/test_keyword_pass.toy b/tests/scripts/keywords/test_keyword_pass.toy similarity index 100% rename from tests/scripts/test_keyword_pass.toy rename to tests/scripts/keywords/test_keyword_pass.toy diff --git a/tests/scripts/test_keyword_print.toy b/tests/scripts/keywords/test_keyword_print.toy similarity index 86% rename from tests/scripts/test_keyword_print.toy rename to tests/scripts/keywords/test_keyword_print.toy index fe63044..efb9b8d 100644 --- a/tests/scripts/test_keyword_print.toy +++ b/tests/scripts/keywords/test_keyword_print.toy @@ -17,5 +17,5 @@ print "\tHello\nworld!"; print "Hello world"[0,5]; //print from a substring, after a concat -print ("hello" .. "world")[2,6]; +print ("hello" .. "world")[3,3]; //should print "low" diff --git a/tests/scripts/test_keyword_return.toy b/tests/scripts/keywords/test_keyword_return.toy similarity index 100% rename from tests/scripts/test_keyword_return.toy rename to tests/scripts/keywords/test_keyword_return.toy diff --git a/tests/scripts/test_keyword_while_break_continue.toy b/tests/scripts/keywords/test_keyword_while_break_continue.toy similarity index 100% rename from tests/scripts/test_keyword_while_break_continue.toy rename to tests/scripts/keywords/test_keyword_while_break_continue.toy diff --git a/tests/scripts/makefile b/tests/scripts/makefile index 7591886..d87a052 100644 --- a/tests/scripts/makefile +++ b/tests/scripts/makefile @@ -20,10 +20,10 @@ endif TEST_ROOTDIR=../.. TEST_SOURCEDIR=$(TEST_ROOTDIR)/$(TOY_SOURCEDIR) TEST_REPLDIR=$(TEST_ROOTDIR)/$(TOY_REPLDIR) -TEST_SCRIPTDIR=. +TEST_SCRIPTDIRS=basics values keywords algorithms #file names -TEST_SCRIPTFILES=$(wildcard $(TEST_SCRIPTDIR)/test_*.toy) +TEST_SCRIPTFILES=$(foreach dir,$(TEST_SCRIPTDIRS), $(wildcard $(dir)/test_*.toy)) #build the source and repl, copy to the local dir, and run all: source repl copy run diff --git a/tests/scripts/test_array.toy b/tests/scripts/test_array.toy deleted file mode 100644 index db61c5e..0000000 --- a/tests/scripts/test_array.toy +++ /dev/null @@ -1,26 +0,0 @@ -//1-D array -var arr = [1, 2, 3]; -arr[1] = 6; - -assert arr == [1, 6, 3], "1-D array failed"; - -//we need to go deeper -var barr = [ - [1, 2, 3], - [4, 5, 6], - [7, 8, 9] -]; - -barr[1][1] = 99; - -assert barr == [[1, 2, 3],[4,99,6],[7,8,9]], "2-D array failed"; - -//test trailing commas -var a = [1, 2, 3, ]; - -print a; - -//test empty arrays -var b = []; - -print b; diff --git a/tests/scripts/test_attribute.toy b/tests/scripts/test_attribute.toy deleted file mode 100644 index 3873d0e..0000000 --- a/tests/scripts/test_attribute.toy +++ /dev/null @@ -1 +0,0 @@ -//URGENT: empty test script \ No newline at end of file diff --git a/tests/scripts/test_function_closures.toy b/tests/scripts/test_function_closures.toy deleted file mode 100644 index 024dbd4..0000000 --- a/tests/scripts/test_function_closures.toy +++ /dev/null @@ -1,22 +0,0 @@ -//closures -fn makeCounter() { - var counter: Int = 0; - - fn increment() { - return ++counter; - } - - return increment; -} - -var tally = makeCounter(); - -while (true) { - var result = tally(); - - print result; - - if (result >= 10) { - break; - } -} diff --git a/tests/scripts/test_function_first_class_citizens.toy b/tests/scripts/test_function_first_class_citizens.toy deleted file mode 100644 index 3ccff2a..0000000 --- a/tests/scripts/test_function_first_class_citizens.toy +++ /dev/null @@ -1,10 +0,0 @@ -//check functions are first class citizens -fn hello() { - print "Hello world"; -} - -fn ident(x) { - return x; -} - -assert ident(hello) == hello, "First class function check failed"; \ No newline at end of file diff --git a/tests/scripts/test_function_invocation_in_arguments.toy b/tests/scripts/test_function_invocation_in_arguments.toy deleted file mode 100644 index 61f096b..0000000 --- a/tests/scripts/test_function_invocation_in_arguments.toy +++ /dev/null @@ -1,11 +0,0 @@ - - -fn a(x) { - assert x == 42; -} - -fn b() { - return 42; -} - -a(b()); \ No newline at end of file diff --git a/tests/scripts/test_functions.toy b/tests/scripts/test_functions.toy deleted file mode 100644 index 3873d0e..0000000 --- a/tests/scripts/test_functions.toy +++ /dev/null @@ -1 +0,0 @@ -//URGENT: empty test script \ No newline at end of file diff --git a/tests/scripts/test_tables.toy b/tests/scripts/test_tables.toy deleted file mode 100644 index 08ad0e8..0000000 --- a/tests/scripts/test_tables.toy +++ /dev/null @@ -1,33 +0,0 @@ -//1-D table -var a = ["alpha": 1, "beta": 2, "gamma": 3]; -a["beta"] = 6; - -print a; -assert a == ["alpha": 1, "beta": 6, "gamma": 3], "1-D tables failed"; - -//nested -var b = [ - "outer": ["inner": true], - "alpha": 1, - "beta": 2, - "gamma": 3 -]; - -print b; -assert b == ["alpha": 1, "beta": 2, "gamma": 3, "outer": ["inner": true]], "nested tables failed"; - -//test empty tables -var empty = [:]; - -print empty; -assert empty == [:], "empty tables failed"; - -//test trailing commas -var trailing = [ - "alpha":1, - "beta":2, - "gamma":3, -]; - -print trailing; -assert trailing == ["alpha": 1, "beta": 2, "gamma": 3], "trailing tables failed"; \ No newline at end of file diff --git a/tests/scripts/test_truthiness.toy b/tests/scripts/test_truthiness.toy deleted file mode 100644 index 222b93f..0000000 --- a/tests/scripts/test_truthiness.toy +++ /dev/null @@ -1,80 +0,0 @@ -//booleans -{ - var value: Bool = true; - - if (value) { - print "boolean"; - } - else { - assert false, "boolean"; - } -} - -{ - var value: Bool = false; - - if (value) { - assert false, "boolean"; - } - else { - print "boolean"; - } -} - -//integers -{ - var value: Int = 42; - - if (value) { - print "integer"; - } - else { - assert false, "integer"; - } -} - -{ - var value: Int = 0; - - if (value) { - assert false, "integer"; - } - else { - print "integer"; - } -} - -//floats -{ - var value: Float = 42.8891; - - if (value) { - print "float"; - } - else { - assert false, "float"; - } -} - -{ - var value: Float = 0; - - if (value) { - assert false, "float"; - } - else { - print "float"; - } -} - -//everything else -{ - var value: String = "foobar"; - - if (value) { - print "string"; - } - else { - assert false, "string"; - } -} \ No newline at end of file diff --git a/tests/scripts/values/test_arrays.toy b/tests/scripts/values/test_arrays.toy new file mode 100644 index 0000000..2212f8a --- /dev/null +++ b/tests/scripts/values/test_arrays.toy @@ -0,0 +1,46 @@ +//1-D array +{ + var array: Array = [1, 2, 3]; + array[1] = 6; + assert array == [1, 6, 3], "1-D array failed"; +} + +//we need to go deeper +{ + var array = [ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9] + ]; + + array[1][1] = 99; + + assert array == [[1, 2, 3],[4,99,6],[7,8,9]], "2-D array failed"; +} + +//attributes +{ + var array = [0,1,2,3,4,5,6,7,8,9]; + assert array.length == 10, "Array length attribute failed"; + + array.pushBack(10); + assert array.length == 11, "Array pushBack attribute failed"; + + array.popBack(); + array.popBack(); + assert array.popBack() == 8, "Array popBack attribute failed"; +} + +//sorting algorithm +{ + //WARN: Array sorting algorithm not yet implemented +} + +//syntax +{ + var empty = []; + assert empty.length == 0, "Empty array failed"; + + var trailing = [1, 2, 3, ]; + assert trailing == [1,2,3], "Trailing comma array failed"; +} diff --git a/tests/scripts/values/test_functions.toy b/tests/scripts/values/test_functions.toy new file mode 100644 index 0000000..3cd93eb --- /dev/null +++ b/tests/scripts/values/test_functions.toy @@ -0,0 +1,55 @@ +//define and invoke a function +{ + + fn greeting() { + return "Hello world"; + } + + assert greeting() == "Hello world", "Function definition failed"; +} + +//functions within other function argument lists +{ + fn outer(arg: String) { + return arg == "Hello world"; + } + + fn inner() { + return "Hello world"; + } + + assert outer(inner()), "Functions within argument lists failed"; +} + +//first class functions +{ + fn hello() { + print "Hello world"; + } + + fn identity(x) { + return x; + } + + assert identity(hello) == hello, "First class functions failed"; +} + +//closures +{ + //closures + fn makeCounter() { + var counter: Int = 0; + fn increment() { + return ++counter; + } + return increment; + } + + var tally: Function = makeCounter(); + + tally(); + tally(); + tally(); + + assert tally() == 4, "closures failed"; +} \ No newline at end of file diff --git a/tests/scripts/values/test_strings.toy b/tests/scripts/values/test_strings.toy new file mode 100644 index 0000000..cd1a895 --- /dev/null +++ b/tests/scripts/values/test_strings.toy @@ -0,0 +1,27 @@ +//declare, define and manipulate strings +{ + var string: String = "Hello World"; + assert string[5] == " ", "String indexing failed"; + + var greeting: String = string[0:5]; + assert greeting == "Hello", "String slicing failed"; + + var parting: String = "Goodbye " .. string[6:5]; + print parting; + assert parting == "Goodbye World", "String concat from an index failed"; + + //WARN: Unbounded slice not possible without indexing from the end of a string + //var simple: String = parting[5:-1]; + //assert simple == "bye World", "String unbounded slice failed"; +} + +//var greeting: String = "Hello World"; +//var parting: String = "Goodbye " .. greeting[6:5]; + +//String attributes +{ + var string: String = "Hello World"; + assert string.length == 11, "string.length failed"; + assert string.asUpper == "HELLO WORLD", "string.asUpper failed"; + assert string.asLower == "hello world", "string.asLower failed"; +} \ No newline at end of file diff --git a/tests/scripts/values/test_tables.toy b/tests/scripts/values/test_tables.toy new file mode 100644 index 0000000..4f1cca5 --- /dev/null +++ b/tests/scripts/values/test_tables.toy @@ -0,0 +1,33 @@ +//1-D table +{ + var table: Table = ["alpha": 1, "beta": 2, "gamma": 3]; + table["beta"] = 6; + assert table == ["alpha": 1, "beta": 6, "gamma": 3], "1-D tables failed"; +} + +//nested +{ + var table: Table = [ + "outer": ["inner": true], + "alpha": 1, + "beta": 2, + "gamma": 3 + ]; + + assert table == ["alpha": 1, "beta": 2, "gamma": 3, "outer": ["inner": true]], "nested tables failed"; +} + +//syntax +{ + var empty = [:]; + assert empty.length == 0, "Empty table failed"; + + var trailing = [ + "alpha":1, + "beta":2, + "gamma":3, + ]; + + assert trailing == ["alpha": 1, "beta": 2, "gamma": 3], "Trailing comma table failed"; +} + diff --git a/tests/units/test_attribute.c b/tests/units/test_attribute.c index e6c5021..0345141 100644 --- a/tests/units/test_attribute.c +++ b/tests/units/test_attribute.c @@ -4,7 +4,7 @@ #include int main(void) { - //URGENT: Test not yet implemented + //WARN: Test not yet implemented printf(TOY_CC_WARN "Test not yet implemented: %s\n" TOY_CC_RESET, __FILE__); return 0; } \ No newline at end of file diff --git a/tests/units/test_function.c b/tests/units/test_function.c index cac9a80..5175bea 100644 --- a/tests/units/test_function.c +++ b/tests/units/test_function.c @@ -117,7 +117,7 @@ int test_functions_from_bytecodes(void) { } int test_functions_from_callbacks(void) { - //URGENT: Test not yet implemented + //WARN: Test not yet implemented printf(TOY_CC_WARN "WIP test not yet implemented: %s\n" TOY_CC_RESET, __FILE__); return 0; } diff --git a/tests/units/test_value.c b/tests/units/test_value.c index c3825e1..477e225 100644 --- a/tests/units/test_value.c +++ b/tests/units/test_value.c @@ -607,9 +607,8 @@ int main(void) { total += res; } - //TODO: references? - //TODO: type coersions? - //TODO: opaques? + //WARN: Testing references not implemented + //WARN: Testing opaques not implemented return total; } \ No newline at end of file