From 0828d17159e2b230a02b7c5c04ebffdfa9707c8e Mon Sep 17 00:00:00 2001 From: Charles KWON OhJun Date: Tue, 31 Mar 2026 10:35:40 +0900 Subject: [PATCH] feat: Harbour RTL vs Go math comparison example + analyzer IMPORT fix - examples/go_math_compare.prg: Side-by-side comparison of Harbour RTL (Abs, Sqrt, Round, Int, Max, Min, Log, Exp, Mod) vs Go math package (Sin, Cos, Pow, Pi, Floor, Ceil, Hypot, ...) - Combined usage: normal distribution, compound interest, distance - Analyzer: recognize IMPORT package names as valid identifiers - Analyzer: add math RTL functions (ABS, SQRT, etc.) to known list Co-Authored-By: Claude Opus 4.6 (1M context) --- compiler/analyzer/analyzer.go | 11 +++ docs/.pdca-status.json | 20 +++- examples/go_math_compare.prg | 179 ++++++++++++++++++++++++++++++++++ 3 files changed, 206 insertions(+), 4 deletions(-) create mode 100644 examples/go_math_compare.prg diff --git a/compiler/analyzer/analyzer.go b/compiler/analyzer/analyzer.go index 51ef51f..86f64fb 100644 --- a/compiler/analyzer/analyzer.go +++ b/compiler/analyzer/analyzer.go @@ -369,6 +369,15 @@ func (a *Analyzer) checkVarUsage(name string, pos token.Position) { return } + // Check if it's an IMPORT package name + for _, imp := range a.file.Imports { + parts := strings.Split(imp.Path, "/") + pkgName := parts[len(parts)-1] + if strings.EqualFold(pkgName, name) || (imp.Alias != "" && imp.Alias == name) { + return + } + } + // Not declared — warn (could be MEMVAR, FIELD, or typo) a.warn(pos, "undeclared variable '%s' (missing LOCAL?)", name) } @@ -407,6 +416,8 @@ func (a *Analyzer) isKnownFunction(name string) bool { "SLEEP": true, "HB_IDLEADD": true, "SECONDS": true, "ERRORBLOCK": true, "BREAK": true, "PCOUNT": true, "PROCNAME": true, "SETPOS": true, "ROW": true, "COL": true, "MAXROW": true, "MAXCOL": true, + "ABS": true, "INT": true, "ROUND": true, "SQRT": true, "LOG": true, "EXP": true, + "MAX": true, "MIN": true, "MOD": true, "SETCOLOR": true, "DISPBOX": true, "DISPBEGIN": true, "DISPEND": true, "HB_SYMBOL_UNUSED": true, "HB_DEFAULT": true, "HB_NTOS": true, } diff --git a/docs/.pdca-status.json b/docs/.pdca-status.json index fd9fb0d..e70eba8 100644 --- a/docs/.pdca-status.json +++ b/docs/.pdca-status.json @@ -1,6 +1,6 @@ { "version": "2.0", - "lastUpdated": "2026-03-31T01:15:54.989Z", + "lastUpdated": "2026-03-31T01:34:48.246Z", "activeFeatures": [ "hbrt", "hbrtl", @@ -253,9 +253,9 @@ "documents": {}, "timestamps": { "started": "2026-03-30T23:02:20.210Z", - "lastUpdated": "2026-03-30T23:04:18.629Z" + "lastUpdated": "2026-03-31T01:34:48.246Z" }, - "lastFile": "/mnt/d/charles/five/compiler/analyzer/analyzer_test.go" + "lastFile": "/mnt/d/charles/five/compiler/analyzer/analyzer.go" } }, "pipeline": { @@ -266,7 +266,7 @@ "session": { "startedAt": "2026-03-27T06:06:49.620Z", "onboardingCompleted": false, - "lastActivity": "2026-03-31T01:15:54.989Z" + "lastActivity": "2026-03-31T01:34:48.246Z" }, "history": [ { @@ -5374,6 +5374,18 @@ "feature": "hbrt", "phase": "do", "action": "updated" + }, + { + "timestamp": "2026-03-31T01:32:45.214Z", + "feature": "analyzer", + "phase": "do", + "action": "updated" + }, + { + "timestamp": "2026-03-31T01:34:48.246Z", + "feature": "analyzer", + "phase": "do", + "action": "updated" } ] } \ No newline at end of file diff --git a/examples/go_math_compare.prg b/examples/go_math_compare.prg new file mode 100644 index 0000000..80d70c1 --- /dev/null +++ b/examples/go_math_compare.prg @@ -0,0 +1,179 @@ +// Five Math Comparison: Harbour RTL vs Go math package +// +// Five has BOTH: +// 1. Harbour built-in: Abs(), Sqrt(), Round(), Int(), Max(), Min(), Log(), Exp(), Mod() +// 2. Go math package: math.Sqrt(), math.Sin(), math.Cos(), math.Pow(), math.Pi, ... +// +// Harbour RTL = simple, familiar. +// Go math = complete, IEEE 754 precise, 60+ functions. +// Five = use BOTH in the same PRG file! + +IMPORT "math" + +PROCEDURE Main() + LOCAL nVal, nH, nG, i + + ? "==============================================" + ? " Five Math: Harbour RTL vs Go math Package" + ? "==============================================" + ? + + // ----------------------------------------------- + // 1. BASIC — Both have these + // ----------------------------------------------- + ? "[1] Abs — absolute value" + nH := Abs(-42.5) + nG := math.Abs(-42.5) + ? " Harbour Abs(-42.5) =", nH + ? " Go math.Abs(-42.5) =", nG + ? " Match:", IIF(nH == nG, "YES", "NO") + ? + + ? "[2] Sqrt — square root" + nH := Sqrt(144) + nG := math.Sqrt(144) + ? " Harbour Sqrt(144) =", nH + ? " Go math.Sqrt(144) =", nG + ? " Match:", IIF(nH == nG, "YES", "NO") + ? + + ? "[3] Int — truncate to integer" + nH := Int(3.7) + nG := math.Trunc(3.7) + ? " Harbour Int(3.7) =", nH + ? " Go math.Trunc(3.7) =", nG + ? " Match:", IIF(nH == nG, "YES", "NO") + ? + + ? "[4] Round — round to decimals" + nH := Round(3.14159, 2) + nG := math.Round(3.14159 * 100) / 100 + ? " Harbour Round(3.14159,2) =", nH + ? " Go math.Round()*100/100 =", nG + ? " Match:", IIF(Abs(nH - nG) < 0.001, "YES", "NO") + ? + + ? "[5] Max / Min" + ? " Harbour Max(10,20) =", Max(10, 20) + ? " Go math.Max(10,20) =", math.Max(10, 20) + ? " Harbour Min(10,20) =", Min(10, 20) + ? " Go math.Min(10,20) =", math.Min(10, 20) + ? + + ? "[6] Log / Exp" + nH := Log(100) + nG := math.Log(100) + ? " Harbour Log(100) =", nH + ? " Go math.Log(100) =", nG + nH := Exp(1) + nG := math.Exp(1) + ? " Harbour Exp(1) =", nH + ? " Go math.Exp(1) =", nG + ? + + ? "[7] Mod" + nH := Mod(17, 5) + nG := math.Mod(17, 5) + ? " Harbour Mod(17,5) =", nH + ? " Go math.Mod(17,5) =", nG + ? + + // ----------------------------------------------- + // 2. GO ONLY — Harbour doesn't have these + // ----------------------------------------------- + ? "==============================================" + ? " Go math ONLY (Harbour has NO equivalent)" + ? "==============================================" + ? + + ? "[8] Trigonometry" + ? " math.Sin(Pi/6) =", math.Sin(math.Pi / 6) + ? " math.Cos(Pi/3) =", math.Cos(math.Pi / 3) + ? " math.Tan(Pi/4) =", math.Tan(math.Pi / 4) + ? " math.Asin(0.5) =", math.Asin(0.5) + ? " math.Atan2(1,1)=", math.Atan2(1, 1) + ? + + ? "[9] Constants" + ? " math.Pi =", math.Pi + ? " math.E =", math.E + ? " math.Phi =", math.Phi + ? " math.Ln2 =", math.Ln2 + ? " math.Sqrt2 =", math.Sqrt2 + ? + + ? "[10] Advanced" + ? " math.Pow(2,10) =", math.Pow(2, 10) + ? " math.Log2(1024) =", math.Log2(1024) + ? " math.Log10(1000) =", math.Log10(1000) + ? " math.Cbrt(27) =", math.Cbrt(27) + ? " math.Hypot(3,4) =", math.Hypot(3, 4) + ? + + ? "[11] Floor / Ceil" + ? " math.Floor(3.7) =", math.Floor(3.7) + ? " math.Ceil(3.2) =", math.Ceil(3.2) + ? " math.Floor(-2.3) =", math.Floor(-2.3) + ? " math.Ceil(-2.7) =", math.Ceil(-2.7) + ? + + ? "[12] Special values" + ? " math.IsNaN(0/0) =", math.IsNaN(math.NaN()) + ? " math.IsInf(1/0,1) =", math.IsInf(math.Inf(1), 1) + ? " math.MaxFloat64 =", math.MaxFloat64 + ? + + // ----------------------------------------------- + // 3. BENCHMARK — Same calculation, both ways + // ----------------------------------------------- + ? "==============================================" + ? " Performance: 10,000 iterations" + ? "==============================================" + ? + + nVal := 0 + FOR i := 1 TO 10000 + nVal += Sqrt(i) + NEXT + ? " Harbour Sqrt x10000 =", Int(nVal) + + nVal := 0 + FOR i := 1 TO 10000 + nVal += math.Sqrt(i) + NEXT + ? " Go math.Sqrt x10000 =", Int(nVal) + ? + + // ----------------------------------------------- + // 4. COMBINED — Use both together! + // ----------------------------------------------- + ? "==============================================" + ? " Combined: Harbour + Go math together" + ? "==============================================" + ? + + ? " Distance between (3,4) and (7,1):" + nVal := math.Hypot(7 - 3, 1 - 4) + ? " = math.Hypot(4, -3) =", Round(nVal, 4) + ? + + ? " Circle area (r=5):" + nVal := math.Pi * math.Pow(5, 2) + ? " = Pi * r^2 =", Round(nVal, 4) + ? + + ? " Compound interest: $1000, 5%, 10 years:" + nVal := 1000 * math.Pow(1.05, 10) + ? " = 1000 * (1.05)^10 =", Round(nVal, 2) + ? + + ? " Normal distribution PDF at x=0 (mean=0, sd=1):" + nVal := (1 / math.Sqrt(2 * math.Pi)) * math.Exp(-0.5 * math.Pow(0, 2)) + ? " =", Round(nVal, 6) + ? + + ? "==============================================" + ? " Five = Harbour simplicity + Go power" + ? "==============================================" + + RETURN