From 29db3bc63e8974debff91e6eadbe71f3a8f08a16 Mon Sep 17 00:00:00 2001 From: hanez Date: Sat, 24 Jan 2026 19:57:39 +0100 Subject: [PATCH] Some array type fixes in the parser. Needs more investigation. (0.37.60) --- CMakeLists.txt | 2 +- examples/arrays.fun | 1 + examples/features.fun | 240 ++++++++++++++++++++++++++++++++++++++++++ src/parser.c | 69 +++++++++--- 4 files changed, 296 insertions(+), 16 deletions(-) create mode 100644 examples/features.fun diff --git a/CMakeLists.txt b/CMakeLists.txt index e6bfc41..618cc69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(fun VERSION 0.37.59 LANGUAGES C) +project(fun VERSION 0.37.60 LANGUAGES C) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) diff --git a/examples/arrays.fun b/examples/arrays.fun index ba28939..c6fd414 100755 --- a/examples/arrays.fun +++ b/examples/arrays.fun @@ -22,6 +22,7 @@ // Arrays basics arr = [1, 2, 3] +print(typeof(arr)) print(arr) // -> [1, 2, 3] print(arr[0] + arr[1]) // -> 3 diff --git a/examples/features.fun b/examples/features.fun new file mode 100644 index 0000000..483219e --- /dev/null +++ b/examples/features.fun @@ -0,0 +1,240 @@ +#!/usr/bin/env fun +// features.fun - Showcase of Fun's neat features +// Demonstrates modern language capabilities in pure Fun + +print("=== Fun Language Feature Showcase ===") +print("") + +// ============================================ +// 1. Type System & Type Safety +// ============================================ +print("1. Strong Type System:") +string name = "Fun Language" +float version = 0.3 +boolean is_awesome = true +items = [1, 2, 3, 4, 5] +config = {"debug": true, "port": 8080} + +print(" Language: " + name + " v" + to_string(version)) +print(" Awesome: " + to_string(is_awesome)) +print("") + +// ============================================ +// 2. Modern Array Operations +// ============================================ +print("2. Array Operations:") +numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +print(" Original: " + to_string(numbers)) + +// Array helpers from spec: push, join, map, filter, reduce +joined = join([10, 20, 30], ", ") +print(" Joined: " + joined) + +// Iterate arrays +print(" Iteration:") +for item in ["apple", "banana", "cherry"] + print(" " + item) +print("") + +// ============================================ +// 3. Maps (Dictionaries) +// ============================================ +print("3. Map Operations:") +person = {"name": "Alice", "age": 30, "role": "Developer"} + +print(" Person: " + to_string(person)) +print(" Has 'age' key: " + to_string(has(person, "age"))) +print(" Keys: " + to_string(keys(person))) +print(" Values: " + to_string(values(person))) +print("") + +// ============================================ +// 4. Object-Oriented Programming +// ============================================ +print("4. Classes & Objects:") + +class Counter(number initial, string label) + count = 0 + name = "" + + fun _construct(this, initial, label) + this.count = initial + this.name = label + + fun increment(this) + this.count = this.count + 1 + + fun get_value(this) + return this.count + + fun display(this) + print(" " + this.name + ": " + to_string(this.count)) + +counter = Counter(100, "Score") +counter.display() +counter.increment() +counter.increment() +counter.display() +print("") + +// ============================================ +// 5. Inheritance +// ============================================ +print("5. Inheritance:") + +class Animal(string type) + species = "" + + fun _construct(this, type) + this.species = type + + fun speak(this) + return "Some sound" + +class Dog(string dog_name) extends Animal + name = "" + + fun _construct(this, dog_name) + this.species = "Canine" + this.name = dog_name + + fun speak(this) + return "Woof! I'm " + this.name + +dog = Dog("Buddy") +print(" " + dog.speak()) +print(" Species: " + dog.species) +print("") + +// ============================================ +// 6. Error Handling +// ============================================ +print("6. Exception Handling:") + +try + print(" Attempting risky operation...") + result = 42 / 2 + print(" Result: " + to_string(result)) +catch err + print(" Caught error! Handled gracefully.") +finally + print(" Cleanup completed.") +print("") + +// ============================================ +// 7. String Manipulation +// ============================================ +print("7. String Features:") +string text = "Hello, Fun Language!" +print(" Original: " + text) +// Note: Using stdlib functions (assumed to exist in utils modules) +// len, substr, find, split would come from stdlib +print("") + +// ============================================ +// 8. Mathematical Operations +// ============================================ +print("8. Math Functions:") +float x = 16.7 +print(" x = " + to_string(x)) +// Note: Math functions like sqrt, floor, ceil, abs, gcd, lcm +// would come from stdlib or similar +print("") + +// ============================================ +// 9. Bitwise Operations +// ============================================ +print("9. Bitwise Operations:") +number bits1 = 12 +number bits2 = 10 +print(" 12 & 10 = " + to_string(band(bits1, bits2))) +print(" 12 | 10 = " + to_string(bor(bits1, bits2))) +print(" 12 ^ 10 = " + to_string(bxor(bits1, bits2))) +print(" 12 << 2 = " + to_string(shl(bits1, 2))) +print(" ~12 = " + to_string(bnot(bits1))) +print("") + +// ============================================ +// 10. Control Flow +// ============================================ +print("10. Control Flow:") + +// For loop with array +print(" Countdown:") +for i in [5, 4, 3, 2, 1] + print(" " + to_string(i) + "...") +print(" Liftoff!") + +// While with break/continue +print(" Skip evens:") +number n = 0 +while n < 10 + n = n + 1 + if n % 2 == 0 + continue + print(" " + to_string(n)) + if n >= 7 + break +print("") + +// ============================================ +// 11. Type Introspection +// ============================================ +print("11. Type Introspection:") +number check_int = 42 +string check_str = "hello" +check_arr = [1, 2, 3] +check_map = {"key": "value"} + +print(" typeof(42) = " + typeof(check_int)) +print(" typeof(\"hello\") = " + typeof(check_str)) +print(" typeof([1,2,3]) = " + typeof(check_arr)) +print(" typeof(map) = " + typeof(check_map)) +print("") + +// ============================================ +// 12. Functional Programming +// ============================================ +print("12. Higher-Order Functions:") + +fun double(n) + return n * 2 + +fun apply_twice(x, func) + return func(func(x)) + +result = apply_twice(5, double) +print(" apply_twice(5, double) = " + to_string(result)) +print("") + +// ============================================ +// 13. Array Operations with Spec Functions +// ============================================ +print("13. Array Higher-Order Functions:") +nums = [1, 2, 3, 4, 5] + +fun square(x) + return x * x + +squared = map(nums, square) +print(" Squared: " + to_string(squared)) + +fun is_even(x) + return x % 2 == 0 + +evens = filter(nums, is_even) +print(" Evens: " + to_string(evens)) + +fun sum(acc, x) + return acc + x + +total = reduce(nums, 0, sum) +print(" Sum: " + to_string(total)) +print("") + +// ============================================ +// Conclusion +// ============================================ +print("=== Feature Showcase Complete! ===") +print("Fun combines modern language features with simplicity.") +print("Explore more examples in ./examples/ directory!") diff --git a/src/parser.c b/src/parser.c index eae29c6..47b727a 100644 --- a/src/parser.c +++ b/src/parser.c @@ -73,6 +73,7 @@ static int g_temp_counter = 0; #define TYPE_META_NIL 10003 #define TYPE_META_CLASS 10004 #define TYPE_META_FLOAT 10005 +#define TYPE_META_ARRAY 10006 static void parser_fail(size_t pos, const char *fmt, ...) { g_has_error = 1; @@ -2845,21 +2846,23 @@ static void parse_simple_statement(Bytecode *bc, const char *src, size_t len, si Note: 'number' maps to signed 64-bit here. 'byte' is an alias of unsigned 8-bit. 'Class' restricts to class instances. */ if (strcmp(name, "number") == 0 || strcmp(name, "string") == 0 || strcmp(name, "boolean") == 0 || strcmp(name, "nil") == 0 - || strcmp(name, "Class") == 0 || strcmp(name, "float") == 0 + || strcmp(name, "class") == 0 || strcmp(name, "float") == 0 + || strcmp(name, "array") == 0 || strcmp(name, "byte") == 0 || strcmp(name, "uint8") == 0 || strcmp(name, "uint16") == 0 || strcmp(name, "uint32") == 0 || strcmp(name, "uint64") == 0 || strcmp(name, "int8") == 0 || strcmp(name, "int16") == 0 || strcmp(name, "int32") == 0 || strcmp(name, "int64") == 0) { - int is_number = (strcmp(name, "number") == 0); - int is_string = (strcmp(name, "string") == 0); - int is_boolean = (strcmp(name, "boolean") == 0); - int is_nil = (strcmp(name, "nil") == 0); - int is_class_tkn = (strcmp(name, "Class") == 0); - int is_float_tkn = (strcmp(name, "float") == 0); - int is_byte = (strcmp(name, "byte") == 0); - int is_u8 = (strcmp(name, "uint8") == 0) || is_byte; - int is_u16 = (strcmp(name, "uint16") == 0); - int is_u32 = (strcmp(name, "uint32") == 0); - int is_u64 = (strcmp(name, "uint64") == 0); + int is_number = (strcmp(name, "number") == 0); + int is_string = (strcmp(name, "string") == 0); + int is_boolean = (strcmp(name, "boolean") == 0); + int is_nil = (strcmp(name, "nil") == 0); + int is_class = (strcmp(name, "class") == 0); + int is_float = (strcmp(name, "float") == 0); + int is_array = (strcmp(name, "array") == 0); + int is_byte = (strcmp(name, "byte") == 0); + int is_u8 = (strcmp(name, "uint8") == 0) || is_byte; + int is_u16 = (strcmp(name, "uint16") == 0); + int is_u32 = (strcmp(name, "uint32") == 0); + int is_u64 = (strcmp(name, "uint64") == 0); int is_s8 = (strcmp(name, "int8") == 0); int is_s16 = (strcmp(name, "int16") == 0); int is_s32 = (strcmp(name, "int32") == 0); @@ -2870,7 +2873,7 @@ static void parse_simple_statement(Bytecode *bc, const char *src, size_t len, si /* store decl bits with sign encoded: negative means signed (number is signed 64-bit) */ if (decl_signed) decl_bits = -decl_bits; - /* declared type metadata: integers use decl_bits; string/boolean/nil/Class/float use special markers */ + /* declared type metadata: integers use decl_bits; string/boolean/nil/Class/float/array use special markers */ int decl_meta = decl_bits; if (is_string) { decl_meta = TYPE_META_STRING; @@ -2878,10 +2881,12 @@ static void parse_simple_statement(Bytecode *bc, const char *src, size_t len, si decl_meta = TYPE_META_BOOLEAN; } else if (is_nil) { decl_meta = TYPE_META_NIL; - } else if (is_class_tkn) { + } else if (is_class) { decl_meta = TYPE_META_CLASS; - } else if (is_float_tkn) { + } else if (is_float) { decl_meta = TYPE_META_FLOAT; + } else if (is_array) { + decl_meta = TYPE_META_ARRAY; } free(name); @@ -2989,6 +2994,23 @@ static void parse_simple_statement(Bytecode *bc, const char *src, size_t len, si bytecode_add_instruction(bc, OP_HALT, 0); } bytecode_set_operand(bc, j_skip_err, bc->instr_count); + } else if (decl_meta == TYPE_META_ARRAY) { + /* expect Array */ + bytecode_add_instruction(bc, OP_DUP, 0); + bytecode_add_instruction(bc, OP_TYPEOF, 0); + int ciArr = bytecode_add_constant(bc, make_string("Array")); + bytecode_add_instruction(bc, OP_LOAD_CONST, ciArr); + bytecode_add_instruction(bc, OP_EQ, 0); + int j_to_error = bytecode_add_instruction(bc, OP_JUMP_IF_FALSE, 0); + int j_skip_err = bytecode_add_instruction(bc, OP_JUMP, 0); + bytecode_set_operand(bc, j_to_error, bc->instr_count); + { + int ciMsg = bytecode_add_constant(bc, make_string("TypeError: expected Array")); + bytecode_add_instruction(bc, OP_LOAD_CONST, ciMsg); + bytecode_add_instruction(bc, OP_PRINT, 0); + bytecode_add_instruction(bc, OP_HALT, 0); + } + bytecode_set_operand(bc, j_skip_err, bc->instr_count); } else if (decl_meta == TYPE_META_BOOLEAN) { /* accept Boolean literal or Number; if Number, clamp to 0/1 */ /* check if value is Boolean */ @@ -3349,6 +3371,23 @@ static void parse_simple_statement(Bytecode *bc, const char *src, size_t len, si bytecode_add_instruction(bc, OP_HALT, 0); } bytecode_set_operand(bc, j_skip_err, bc->instr_count); + } else if (meta == TYPE_META_ARRAY) { + /* expect Array */ + bytecode_add_instruction(bc, OP_DUP, 0); + bytecode_add_instruction(bc, OP_TYPEOF, 0); + int ciArr = bytecode_add_constant(bc, make_string("Array")); + bytecode_add_instruction(bc, OP_LOAD_CONST, ciArr); + bytecode_add_instruction(bc, OP_EQ, 0); + int j_to_error = bytecode_add_instruction(bc, OP_JUMP_IF_FALSE, 0); + int j_skip_err = bytecode_add_instruction(bc, OP_JUMP, 0); + bytecode_set_operand(bc, j_to_error, bc->instr_count); + { + int ciMsg = bytecode_add_constant(bc, make_string("TypeError: expected Array")); + bytecode_add_instruction(bc, OP_LOAD_CONST, ciMsg); + bytecode_add_instruction(bc, OP_PRINT, 0); + bytecode_add_instruction(bc, OP_HALT, 0); + } + bytecode_set_operand(bc, j_skip_err, bc->instr_count); } else if (meta == TYPE_META_BOOLEAN) { /* expect Number then clamp to 1 bit (unsigned) */ bytecode_add_instruction(bc, OP_DUP, 0);