feat(oop): METHOD ... INLINE <expr> and MESSAGE handlers

Harbour's inline-method sugar was parsed but the body was skipped,
leaving any `METHOD X() INLINE expr` declaration registered in the
class vtable with no matching HB_<CLASS>_X function — link error
at build time.

Parser: MethodDecl gains an InlineBody Expr field. parseClassMethodDecl
captures the expression after INLINE instead of skipping to EOL.
New parseMessageDecl handles `MESSAGE <name> [(params)] INLINE expr`
and returns the same MethodDecl shape.

Codegen: emitClassDecl walks members a second time after the class
registration init block and emits emitInlineMethodBody for each
IsInline method — a Frame(nParams, 0) + emitExpr(InlineBody) +
RetValue function. curMethodClass is bound so ::super: inside an
inline body still resolves.

Tested (/tmp/test_inline.prg): all four patterns — bare INLINE,
MESSAGE INLINE, INLINE with params, INLINE reading ::field —
produce expected values.

FiveSql2 43/43, Harbour compat 56/56, Go test ALL PASS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-18 15:41:36 +09:00
parent 3a56bd321a
commit 34485cd6c8
3 changed files with 115 additions and 9 deletions

View File

@@ -177,6 +177,7 @@ type MethodDecl struct {
ClassName string // METHOD name CLASS classname (standalone)
Params []*ParamDecl
IsInline bool // INLINE method
InlineBody Expr // inline expression body — `RETURN <expr>` equivalent
IsSetGet bool // METHOD name(x) SETGET — getter if no arg, setter if arg
IsAccess bool // ACCESS name METHOD getterName
IsAssign bool // ASSIGN name METHOD setterName