Files
five/hbrt/macroeval_test.go
Charles KWON OhJun 59568f3301 Five v0.9 — Harbour + Go fusion language
- Compiler: PP → Lexer → Parser → Analyzer → Gengo pipeline
- Parser: 232/236 (98%) Harbour compatibility, registry-based dispatch
- RTL: 351 Harbour-compatible functions
- RDD: DBF/NTX/CDX engines with Rushmore bitmap optimization
- Go Interop: IMPORT + pkg.Func() + obj:Method() with FastPath (15M calls/sec)
- HB_FUNC API: Full Harbour C API compatible Go bridge
- Concurrency: SPAWN/LAUNCH/GOROUTINE, <-, WATCH, PARALLEL FOR, ASYNC/AWAIT
- Extensions: Multi-return, DEFER, Slice, f-string, Nil-safe ?:, CONST
- Macro Compiler: Runtime AST parsing and evaluation
- Debugger: TUI debugger with source display, breakpoints, stepping
- FRB: Native + Pcode dual mode runtime binary
- Tests: 13 packages ALL PASS

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 09:41:50 +09:00

143 lines
3.2 KiB
Go

package hbrt
import (
"testing"
)
func TestMacroEval_Literal(t *testing.T) {
vm := NewVM()
th := vm.NewThread()
th.Frame(0, 0)
// Numbers
v := th.MacroEval("42")
if v.AsInt() != 42 { t.Errorf("int: got %v", v) }
v = th.MacroEval("3.14")
if v.AsDouble()-3.14 > 0.001 { t.Errorf("float: got %v", v) }
// Strings
v = th.MacroEval(`"hello"`)
if v.AsString() != "hello" { t.Errorf("string: got %v", v) }
// Booleans
v = th.MacroEval(".T.")
if !v.AsBool() { t.Errorf("true: got %v", v) }
v = th.MacroEval(".F.")
if v.AsBool() { t.Errorf("false: got %v", v) }
// NIL
v = th.MacroEval("NIL")
// returns string "NIL" for now (identifier)
if v.AsString() != "NIL" { t.Errorf("nil: got %v", v) }
}
func TestMacroEval_Arithmetic(t *testing.T) {
vm := NewVM()
th := vm.NewThread()
th.Frame(0, 0)
v := th.MacroEval("2 + 3")
if v.AsInt() != 5 { t.Errorf("add: got %v", v) }
v = th.MacroEval("10 - 4")
if v.AsInt() != 6 { t.Errorf("sub: got %v", v) }
v = th.MacroEval("6 * 7")
if v.AsInt() != 42 { t.Errorf("mul: got %v", v) }
v = th.MacroEval("100 / 4")
if int(v.AsNumDouble()) != 25 { t.Errorf("div: got %v", v.AsNumDouble()) }
v = th.MacroEval("2 ** 10")
if int(v.AsNumDouble()) != 1024 { t.Errorf("pow: got %v", v.AsNumDouble()) }
}
func TestMacroEval_StringOps(t *testing.T) {
vm := NewVM()
th := vm.NewThread()
th.Frame(0, 0)
v := th.MacroEval(`"hello" + " " + "world"`)
if v.AsString() != "hello world" { t.Errorf("concat: got %q", v.AsString()) }
}
func TestMacroEval_Comparison(t *testing.T) {
vm := NewVM()
th := vm.NewThread()
th.Frame(0, 0)
v := th.MacroEval("10 > 5")
if !v.AsBool() { t.Errorf("gt: got %v", v) }
v = th.MacroEval("3 < 1")
if v.AsBool() { t.Errorf("lt: got %v", v) }
v = th.MacroEval("5 == 5")
if !v.AsBool() { t.Errorf("eq: got %v", v) }
v = th.MacroEval("5 != 3")
if !v.AsBool() { t.Errorf("neq: got %v", v) }
}
func TestMacroEval_Complex(t *testing.T) {
vm := NewVM()
th := vm.NewThread()
th.Frame(0, 0)
v := th.MacroEval("(2 + 3) * 4")
if v.AsInt() != 20 { t.Errorf("complex: got %v", v) }
v = th.MacroEval(`"abc" + "def"`)
if v.AsString() != "abcdef" { t.Errorf("strcat: got %q", v.AsString()) }
}
func TestMacroEval_FunctionCall(t *testing.T) {
vm := NewVM()
// Register a test function
vm.RegisterSymbol(&Symbol{
Name: "DOUBLE",
Func: func(t *Thread) {
t.Frame(1, 0)
defer t.EndProc()
n := t.Local(1).AsInt()
t.PushInt(n * 2)
t.RetValue()
},
})
th := vm.NewThread()
th.Frame(0, 0)
v := th.MacroEval("Double(21)")
if v.AsInt() != 42 { t.Errorf("funcall: got %v", v) }
}
func TestMacroEval_Array(t *testing.T) {
vm := NewVM()
th := vm.NewThread()
th.Frame(0, 0)
v := th.MacroEval(`{1, 2, 3}`)
if !v.IsArray() { t.Fatalf("array: not array") }
arr := v.AsArray()
if len(arr.Items) != 3 { t.Fatalf("array: len=%d", len(arr.Items)) }
if arr.Items[0].AsInt() != 1 || arr.Items[2].AsInt() != 3 {
t.Errorf("array: got %v %v", arr.Items[0], arr.Items[2])
}
}
func TestMacroEval_Empty(t *testing.T) {
vm := NewVM()
th := vm.NewThread()
th.Frame(0, 0)
v := th.MacroEval("")
if !v.IsNil() { t.Errorf("empty: got %v", v) }
v = th.MacroEval(" ")
if !v.IsNil() { t.Errorf("whitespace: got %v", v) }
}