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) <noreply@anthropic.com>
This commit is contained in:
2026-03-31 10:35:40 +09:00
parent e04ae563ef
commit 0828d17159
3 changed files with 206 additions and 4 deletions

View File

@@ -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,
}

View File

@@ -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"
}
]
}

View File

@@ -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