diff --git a/internal/compiler/funchandler.go b/internal/compiler/funchandler.go index 6d0b218..377d72e 100644 --- a/internal/compiler/funchandler.go +++ b/internal/compiler/funchandler.go @@ -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) } } diff --git a/internal/compiler/funchandler_test.go b/internal/compiler/funchandler_test.go index ad27d9c..0b78536 100644 --- a/internal/compiler/funchandler_test.go +++ b/internal/compiler/funchandler_test.go @@ -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) {