Some array type fixes in the parser. Needs more investigation. (0.37.60)
This commit is contained in:
parent
97cfc74a01
commit
29db3bc63e
4 changed files with 296 additions and 16 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.10)
|
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 99)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
// Arrays basics
|
// Arrays basics
|
||||||
arr = [1, 2, 3]
|
arr = [1, 2, 3]
|
||||||
|
print(typeof(arr))
|
||||||
print(arr) // -> [1, 2, 3]
|
print(arr) // -> [1, 2, 3]
|
||||||
print(arr[0] + arr[1]) // -> 3
|
print(arr[0] + arr[1]) // -> 3
|
||||||
|
|
||||||
|
|
|
||||||
240
examples/features.fun
Normal file
240
examples/features.fun
Normal file
|
|
@ -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 <utils/math.fun> 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!")
|
||||||
69
src/parser.c
69
src/parser.c
|
|
@ -73,6 +73,7 @@ static int g_temp_counter = 0;
|
||||||
#define TYPE_META_NIL 10003
|
#define TYPE_META_NIL 10003
|
||||||
#define TYPE_META_CLASS 10004
|
#define TYPE_META_CLASS 10004
|
||||||
#define TYPE_META_FLOAT 10005
|
#define TYPE_META_FLOAT 10005
|
||||||
|
#define TYPE_META_ARRAY 10006
|
||||||
|
|
||||||
static void parser_fail(size_t pos, const char *fmt, ...) {
|
static void parser_fail(size_t pos, const char *fmt, ...) {
|
||||||
g_has_error = 1;
|
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.
|
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
|
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, "byte") == 0
|
||||||
|| strcmp(name, "uint8") == 0 || strcmp(name, "uint16") == 0 || strcmp(name, "uint32") == 0 || strcmp(name, "uint64") == 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) {
|
|| 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_number = (strcmp(name, "number") == 0);
|
||||||
int is_string = (strcmp(name, "string") == 0);
|
int is_string = (strcmp(name, "string") == 0);
|
||||||
int is_boolean = (strcmp(name, "boolean") == 0);
|
int is_boolean = (strcmp(name, "boolean") == 0);
|
||||||
int is_nil = (strcmp(name, "nil") == 0);
|
int is_nil = (strcmp(name, "nil") == 0);
|
||||||
int is_class_tkn = (strcmp(name, "Class") == 0);
|
int is_class = (strcmp(name, "class") == 0);
|
||||||
int is_float_tkn = (strcmp(name, "float") == 0);
|
int is_float = (strcmp(name, "float") == 0);
|
||||||
int is_byte = (strcmp(name, "byte") == 0);
|
int is_array = (strcmp(name, "array") == 0);
|
||||||
int is_u8 = (strcmp(name, "uint8") == 0) || is_byte;
|
int is_byte = (strcmp(name, "byte") == 0);
|
||||||
int is_u16 = (strcmp(name, "uint16") == 0);
|
int is_u8 = (strcmp(name, "uint8") == 0) || is_byte;
|
||||||
int is_u32 = (strcmp(name, "uint32") == 0);
|
int is_u16 = (strcmp(name, "uint16") == 0);
|
||||||
int is_u64 = (strcmp(name, "uint64") == 0);
|
int is_u32 = (strcmp(name, "uint32") == 0);
|
||||||
|
int is_u64 = (strcmp(name, "uint64") == 0);
|
||||||
int is_s8 = (strcmp(name, "int8") == 0);
|
int is_s8 = (strcmp(name, "int8") == 0);
|
||||||
int is_s16 = (strcmp(name, "int16") == 0);
|
int is_s16 = (strcmp(name, "int16") == 0);
|
||||||
int is_s32 = (strcmp(name, "int32") == 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) */
|
/* store decl bits with sign encoded: negative means signed (number is signed 64-bit) */
|
||||||
if (decl_signed) decl_bits = -decl_bits;
|
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;
|
int decl_meta = decl_bits;
|
||||||
if (is_string) {
|
if (is_string) {
|
||||||
decl_meta = TYPE_META_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;
|
decl_meta = TYPE_META_BOOLEAN;
|
||||||
} else if (is_nil) {
|
} else if (is_nil) {
|
||||||
decl_meta = TYPE_META_NIL;
|
decl_meta = TYPE_META_NIL;
|
||||||
} else if (is_class_tkn) {
|
} else if (is_class) {
|
||||||
decl_meta = TYPE_META_CLASS;
|
decl_meta = TYPE_META_CLASS;
|
||||||
} else if (is_float_tkn) {
|
} else if (is_float) {
|
||||||
decl_meta = TYPE_META_FLOAT;
|
decl_meta = TYPE_META_FLOAT;
|
||||||
|
} else if (is_array) {
|
||||||
|
decl_meta = TYPE_META_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(name);
|
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_add_instruction(bc, OP_HALT, 0);
|
||||||
}
|
}
|
||||||
bytecode_set_operand(bc, j_skip_err, bc->instr_count);
|
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) {
|
} else if (decl_meta == TYPE_META_BOOLEAN) {
|
||||||
/* accept Boolean literal or Number; if Number, clamp to 0/1 */
|
/* accept Boolean literal or Number; if Number, clamp to 0/1 */
|
||||||
/* check if value is Boolean */
|
/* 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_add_instruction(bc, OP_HALT, 0);
|
||||||
}
|
}
|
||||||
bytecode_set_operand(bc, j_skip_err, bc->instr_count);
|
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) {
|
} else if (meta == TYPE_META_BOOLEAN) {
|
||||||
/* expect Number then clamp to 1 bit (unsigned) */
|
/* expect Number then clamp to 1 bit (unsigned) */
|
||||||
bytecode_add_instruction(bc, OP_DUP, 0);
|
bytecode_add_instruction(bc, OP_DUP, 0);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue