Skip to content
3 changes: 2 additions & 1 deletion ERRORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ JSON module errors
| E13001 | json-syntax-error | invalid JSON syntax |
| E13002 | json-unsupported-type | type cannot be converted to JSON |
| E13003 | json-invalid-map-key | JSON object keys must be strings |
| E13004 | json-decode-requires-type | json.decode() requires a type argument |

## Code Style Warnings (W1xxx)

Expand Down Expand Up @@ -373,4 +374,4 @@ Module-related warnings

## Summary

**Total:** 255 error/warning codes
**Total:** 256 error/warning codes
20 changes: 11 additions & 9 deletions cmd/ez/repl.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ func startREPL() {
}

// Handle REPL commands
if newEnv := handleReplCommand(line, env); newEnv != nil {
env = newEnv
if newEnv, handled := handleReplCommand(line, env); handled {
if newEnv != nil {
env = newEnv
}
continue
}

Expand All @@ -73,33 +75,33 @@ func startREPL() {
}

// handleReplCommand handles special REPL commands
// Returns a new environment if the environment should be reset, nil otherwise
func handleReplCommand(line string, env *interpreter.Environment) *interpreter.Environment {
// Returns (new environment if reset, whether command was handled)
func handleReplCommand(line string, env *interpreter.Environment) (*interpreter.Environment, bool) {
switch line {
case "exit", "quit":
fmt.Println("Goodbye!")
os.Exit(0)
return nil
return nil, true

case "clear":
// Clear the terminal screen only
fmt.Print("\033[H\033[2J")
return nil
return nil, true

case "reset":
// Clear the terminal screen AND reset the environment
fmt.Print("\033[H\033[2J")
fmt.Printf("EZ Language REPL %s\n", Version)
fmt.Println("Type 'help' for commands, 'exit' or 'quit' to exit")
fmt.Println()
return interpreter.NewEnvironment()
return interpreter.NewEnvironment(), true

case "help":
printReplHelp()
return nil
return nil, true
}

return nil
return nil, false
}

// printReplHelp prints REPL help information
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/fail/errors/E5005_integer_overflow_add.ez
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
*/

do main() {
temp max int = 9223372036854775807 // max int64
temp result int = max + 1 // Overflow
temp max i64 = 9223372036854775807 // max i64
temp result i64 = max + 1 // Overflow
}
4 changes: 2 additions & 2 deletions integration-tests/fail/errors/E5006_integer_overflow_sub.ez
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
*/

do main() {
temp min int = -9223372036854775808 // min int64
temp result int = min - 1 // Underflow
temp min i64 = -9223372036854775808 // min i64
temp result i64 = min - 1 // Underflow
}
4 changes: 2 additions & 2 deletions integration-tests/fail/errors/E5007_integer_overflow_mul.ez
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
*/

do main() {
temp max int = 9223372036854775807 // max int64
temp result int = max * 2 // Overflow
temp max i64 = 9223372036854775807 // max i64
temp result i64 = max * 2 // Overflow
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
*/

do main() {
temp max int = 9223372036854775807 // max int64
temp max i64 = 9223372036854775807 // max i64
max++ // Overflow
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
*/

do main() {
temp min int = -9223372036854775808 // min int64
temp min i64 = -9223372036854775808 // min i64
min-- // Underflow
}
22 changes: 11 additions & 11 deletions integration-tests/pass/stdlib/os.ez
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@ do main() {
println(" -- Environment Variables --")

// Test 1: get_env for PATH (should exist on all systems)
temp path_value = os.get_env("PATH")
if path_value != nil && len(path_value) > 0 {
temp path_value, path_err = os.get_env("PATH")
if path_err == nil && len(path_value) > 0 {
println(" [PASS] os.get_env('PATH') exists")
passed += 1
} otherwise {
println(" [FAIL] os.get_env('PATH'): expected non-nil")
println(" [FAIL] os.get_env('PATH'): expected to exist")
failed += 1
}

// Test 2: get_env for non-existent variable
temp nonexistent = os.get_env("EZ_NONEXISTENT_VAR_12345")
if nonexistent == nil {
println(" [PASS] os.get_env(nonexistent) = nil")
temp nonexistent, nonexistent_err = os.get_env("EZ_NONEXISTENT_VAR_12345")
if nonexistent_err != nil {
println(" [PASS] os.get_env(nonexistent) returns error")
passed += 1
} otherwise {
println(" [FAIL] os.get_env(nonexistent): expected nil")
println(" [FAIL] os.get_env(nonexistent): expected error")
failed += 1
}

Expand All @@ -44,8 +44,8 @@ do main() {
}

// Test 4: verify set_env worked
temp verify_value = os.get_env("EZ_TEST_VAR")
if verify_value == "test_value_123" {
temp verify_value, verify_err = os.get_env("EZ_TEST_VAR")
if verify_err == nil && verify_value == "test_value_123" {
println(" [PASS] os.get_env() verified set value")
passed += 1
} otherwise {
Expand All @@ -64,8 +64,8 @@ do main() {
}

// Test 6: verify unset worked
temp after_unset = os.get_env("EZ_TEST_VAR")
if after_unset == nil {
temp after_unset, after_unset_err = os.get_env("EZ_TEST_VAR")
if after_unset_err != nil {
println(" [PASS] variable correctly unset")
passed += 1
} otherwise {
Expand Down
27 changes: 27 additions & 0 deletions integration-tests/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,33 @@ for dir in "$SCRIPT_DIR"/pass/multi-file/*/; do
fi
done

# Warning tests (should produce specific warnings when checked)
if [ -d "$SCRIPT_DIR/pass/warnings" ]; then
echo ""
echo "Running WARNING tests (expecting specific warnings)..."
echo "----------------------------------------"

for test_file in "$SCRIPT_DIR"/pass/warnings/*.ez; do
if [ -f "$test_file" ]; then
test_name=$(basename "$test_file" .ez)
# Extract expected warning code from filename (e.g., W2010_something.ez -> W2010)
expected_warning=$(echo "$test_name" | grep -oE '^W[0-9]+')
printf " warnings/%s... " "$test_name"

# Run ez check (not full execution) to get warnings
output=$("$EZ_BIN" check "$test_file" 2>&1) || true

if echo "$output" | grep -q "warning\[$expected_warning\]"; then
echo -e "${GREEN}PASS${NC}"
((PASS_COUNT++))
else
echo -e "${RED}FAIL${NC} (expected warning $expected_warning not found)"
((FAIL_COUNT++))
fi
fi
done
fi

echo ""
echo "Running FAIL tests (expecting errors)..."
echo "----------------------------------------"
Expand Down
1 change: 1 addition & 0 deletions pkg/errors/codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ var (
E13001 = ErrorCode{"E13001", "json-syntax-error", "invalid JSON syntax"}
E13002 = ErrorCode{"E13002", "json-unsupported-type", "type cannot be converted to JSON"}
E13003 = ErrorCode{"E13003", "json-invalid-map-key", "JSON object keys must be strings"}
E13004 = ErrorCode{"E13004", "json-decode-requires-type", "json.decode() requires a type argument"}
)

// =============================================================================
Expand Down
18 changes: 18 additions & 0 deletions pkg/interpreter/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func init() {

// getEZTypeName returns the EZ language type name for an object
// For integers, returns the declared type (e.g., "u64", "i32") instead of generic "INTEGER"
// For arrays and maps, returns the typed format (e.g., "[string]", "map[string:int]")
func getEZTypeName(obj Object) string {
switch v := obj.(type) {
case *Integer:
Expand All @@ -38,8 +39,14 @@ func getEZTypeName(obj Object) string {
case *Byte:
return "byte"
case *Array:
if v.ElementType != "" {
return "[" + v.ElementType + "]"
}
return "array"
case *Map:
if v.KeyType != "" && v.ValueType != "" {
return "map[" + v.KeyType + ":" + v.ValueType + "]"
}
return "map"
case *Struct:
if v.TypeName != "" {
Expand All @@ -52,6 +59,17 @@ func getEZTypeName(obj Object) string {
return "nil"
case *Function:
return "function"
case *Range:
return "Range<int>"
case *FileHandle:
return "File"
case *Database:
return "Database"
case *Reference:
if inner, ok := v.Deref(); ok {
return "Ref<" + getEZTypeName(inner) + ">"
}
return "Ref"
default:
return string(obj.Type())
}
Expand Down
Loading
Loading