Fixed so functions can do type conversion between in/out params and arguments. Lossy conversions give a warning now.

This commit is contained in:
Mattias Hansson 2025-12-12 14:11:31 +01:00
parent b830a41b5f
commit 5f01282df5
2 changed files with 38 additions and 18 deletions

View file

@ -386,42 +386,60 @@ func (fh *FunctionHandler) processStringArg(arg string, param *FuncParam, funcNa
return nil
}
// processVarArg handles variable arguments
func (fh *FunctionHandler) processVarArg(sym *Symbol, param *FuncParam, funcName string, line preproc.Line, inAssigns, outAssigns *[]string) error {
// Check type compatibility
if (sym.IsByte() && param.Symbol.IsWord()) || (sym.IsWord() && param.Symbol.IsByte()) {
return fmt.Errorf("%s:%d: CALL %s: type mismatch for parameter %s", line.Filename, line.LineNo, funcName, param.Symbol.Name)
}
if sym.IsConst() {
return fmt.Errorf("%s:%d: CALL %s: cannot pass constant to function", line.Filename, line.LineNo, funcName)
}
// Generate IN assignments
// Generate IN assignments (sym -> param)
if param.Direction.Has(DirIn) {
*inAssigns = append(*inAssigns,
fmt.Sprintf(" lda %s", sym.FullName()),
fmt.Sprintf(" sta %s", param.Symbol.FullName()),
)
if sym.IsWord() {
*inAssigns = append(*inAssigns,
fmt.Sprintf(" lda %s+1", sym.FullName()),
fmt.Sprintf(" sta %s+1", param.Symbol.FullName()),
)
if param.Symbol.IsWord() {
if sym.IsWord() {
*inAssigns = append(*inAssigns,
fmt.Sprintf(" lda %s+1", sym.FullName()),
fmt.Sprintf(" sta %s+1", param.Symbol.FullName()),
)
} else {
// byte -> word: zero extend
*inAssigns = append(*inAssigns,
" lda #0",
fmt.Sprintf(" sta %s+1", param.Symbol.FullName()),
)
}
} else if sym.IsWord() {
// word -> byte: lossy
fmt.Printf("%s:%d: warning: CALL %s: truncating word '%s' to byte parameter '%s'\n",
line.Filename, line.LineNo, funcName, sym.Name, param.Symbol.Name)
}
}
// Generate OUT assignments
// Generate OUT assignments (param -> sym)
if param.Direction.Has(DirOut) {
*outAssigns = append(*outAssigns,
fmt.Sprintf(" lda %s", param.Symbol.FullName()),
fmt.Sprintf(" sta %s", sym.FullName()),
)
if sym.IsWord() {
*outAssigns = append(*outAssigns,
fmt.Sprintf(" lda %s+1", param.Symbol.FullName()),
fmt.Sprintf(" sta %s+1", sym.FullName()),
)
if param.Symbol.IsWord() {
*outAssigns = append(*outAssigns,
fmt.Sprintf(" lda %s+1", param.Symbol.FullName()),
fmt.Sprintf(" sta %s+1", sym.FullName()),
)
} else {
// byte -> word: zero extend
*outAssigns = append(*outAssigns,
" lda #0",
fmt.Sprintf(" sta %s+1", sym.FullName()),
)
}
} else if param.Symbol.IsWord() {
// word -> byte: lossy
fmt.Printf("%s:%d: warning: CALL %s: truncating word parameter '%s' to byte '%s'\n",
line.Filename, line.LineNo, funcName, param.Symbol.Name, sym.Name)
}
}

View file

@ -587,6 +587,8 @@ func TestHandleFuncCall_Errors(t *testing.T) {
line: "CALL test ( 1 2 )",
wantErr: "expected 1 arguments, got 2",
},
//
/* This is no error anymore, just a warning.
{
name: "type mismatch",
setup: func(fh *FunctionHandler, st *SymbolTable) {
@ -596,7 +598,7 @@ func TestHandleFuncCall_Errors(t *testing.T) {
},
line: "CALL test ( wvar )",
wantErr: "type mismatch",
},
}, */
{
name: "const to out param",
setup: func(fh *FunctionHandler, st *SymbolTable) {