mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
first steps to support multiple args in pipe expressions
This commit is contained in:
parent
942c5cc04b
commit
7c121bfc01
@ -442,11 +442,11 @@ class AsmGen(internal val program: Program,
|
|||||||
internal fun translateBuiltinFunctionCallExpression(bfc: BuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) =
|
internal fun translateBuiltinFunctionCallExpression(bfc: BuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) =
|
||||||
builtinFunctionsAsmGen.translateFunctioncallExpression(bfc, resultToStack, resultRegister)
|
builtinFunctionsAsmGen.translateFunctioncallExpression(bfc, resultToStack, resultRegister)
|
||||||
|
|
||||||
private fun translateBuiltinFunctionCallExpression(name: String, singleArg:AsmAssignSource, scope: Subroutine): DataType =
|
private fun translateBuiltinFunctionCallExpression(bfc: IFunctionCall, firstArg: AsmAssignSource, scope: Subroutine): DataType =
|
||||||
builtinFunctionsAsmGen.translateUnaryFunctioncall(name, singleArg, false, scope)
|
builtinFunctionsAsmGen.translateFunctionCallWithFirstArg(bfc, firstArg, false, scope)
|
||||||
|
|
||||||
private fun translateBuiltinFunctionCallStatement(name: String, singleArg: AsmAssignSource, scope: Subroutine) =
|
private fun translateBuiltinFunctionCallStatement(bfc: IFunctionCall, firstArg: AsmAssignSource, scope: Subroutine) =
|
||||||
builtinFunctionsAsmGen.translateUnaryFunctioncall(name, singleArg, true, scope)
|
builtinFunctionsAsmGen.translateFunctionCallWithFirstArg(bfc, firstArg, true, scope)
|
||||||
|
|
||||||
internal fun translateFunctionCall(functionCallExpr: FunctionCallExpression, isExpression: Boolean) =
|
internal fun translateFunctionCall(functionCallExpr: FunctionCallExpression, isExpression: Boolean) =
|
||||||
functioncallAsmGen.translateFunctionCall(functionCallExpr, isExpression)
|
functioncallAsmGen.translateFunctionCall(functionCallExpr, isExpression)
|
||||||
@ -2829,20 +2829,20 @@ $repeatLabel lda $counterVar
|
|||||||
AsmAssignSource.fromAstSource(source, program, this)
|
AsmAssignSource.fromAstSource(source, program, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
// the segments (except the last one): unary function calls taking a single param and producing a value.
|
// the segments (except the last one): function calls taking one or more parameters and producing a value.
|
||||||
// directly assign their argument from the previous call's returnvalue.
|
// directly assign their first argument from the previous call's returnvalue (and take the rest, if any, from the call itself)
|
||||||
segments.dropLast(1).forEach {
|
segments.dropLast(1).forEach {
|
||||||
it as IFunctionCall
|
it as IFunctionCall
|
||||||
valueDt = translateUnaryFunctionCallWithArgSource(it.target, valueSource, false, subroutine)
|
valueDt = translateFunctionCallWithFirstArg(it, valueSource, false, subroutine)
|
||||||
val resultReg = returnRegisterOfFunction(it.target)
|
val resultReg = returnRegisterOfFunction(it.target)
|
||||||
valueSource = AsmAssignSource(SourceStorageKind.REGISTER, program, this, valueDt, register = resultReg)
|
valueSource = AsmAssignSource(SourceStorageKind.REGISTER, program, this, valueDt, register = resultReg)
|
||||||
}
|
}
|
||||||
// the last segment: unary function call taking a single param and optionally producing a result value.
|
// the last segment: function call taking one or more parameters and optionally producing a result value.
|
||||||
val lastCall = segments.last() as IFunctionCall
|
val lastCall = segments.last() as IFunctionCall
|
||||||
if(isStatement) {
|
if(isStatement) {
|
||||||
translateUnaryFunctionCallWithArgSource(lastCall.target, valueSource, true, subroutine)
|
translateFunctionCallWithFirstArg(lastCall, valueSource, true, subroutine)
|
||||||
} else {
|
} else {
|
||||||
valueDt = translateUnaryFunctionCallWithArgSource(lastCall.target, valueSource, false, subroutine)
|
valueDt = translateFunctionCallWithFirstArg(lastCall, valueSource, false, subroutine)
|
||||||
if(pushResultOnEstack) {
|
if(pushResultOnEstack) {
|
||||||
when (valueDt) {
|
when (valueDt) {
|
||||||
in ByteDatatypes -> {
|
in ByteDatatypes -> {
|
||||||
@ -2860,14 +2860,23 @@ $repeatLabel lda $counterVar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateUnaryFunctionCallWithArgSource(target: IdentifierReference, singleArg: AsmAssignSource, isStatement: Boolean, scope: Subroutine): DataType {
|
private fun translateFunctionCallWithFirstArg(
|
||||||
when(val targetStmt = target.targetStatement(program)!!) {
|
fcall: IFunctionCall,
|
||||||
|
firstArg: AsmAssignSource,
|
||||||
|
isStatement: Boolean,
|
||||||
|
scope: Subroutine
|
||||||
|
): DataType {
|
||||||
|
|
||||||
|
if(fcall.args.isNotEmpty())
|
||||||
|
TODO("deal with additional args (non-unary function): ${fcall.target.nameInSource} (... , ${fcall.args.joinToString(", ")})")
|
||||||
|
|
||||||
|
when(val targetStmt = fcall.target.targetStatement(program)!!) {
|
||||||
is BuiltinFunctionPlaceholder -> {
|
is BuiltinFunctionPlaceholder -> {
|
||||||
return if(isStatement) {
|
return if(isStatement) {
|
||||||
translateBuiltinFunctionCallStatement(targetStmt.name, singleArg, scope)
|
translateBuiltinFunctionCallStatement(fcall, firstArg, scope)
|
||||||
DataType.UNDEFINED
|
DataType.UNDEFINED
|
||||||
} else {
|
} else {
|
||||||
translateBuiltinFunctionCallExpression(targetStmt.name, singleArg, scope)
|
translateBuiltinFunctionCallExpression(fcall, firstArg, scope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Subroutine -> {
|
is Subroutine -> {
|
||||||
@ -2876,9 +2885,9 @@ $repeatLabel lda $counterVar
|
|||||||
// argument via registers
|
// argument via registers
|
||||||
val argRegister = targetStmt.asmParameterRegisters.single().registerOrPair!!
|
val argRegister = targetStmt.asmParameterRegisters.single().registerOrPair!!
|
||||||
val assignArgument = AsmAssignment(
|
val assignArgument = AsmAssignment(
|
||||||
singleArg,
|
firstArg,
|
||||||
AsmAssignTarget.fromRegisters(argRegister, argDt in SignedDatatypes, scope, program, this),
|
AsmAssignTarget.fromRegisters(argRegister, argDt in SignedDatatypes, scope, program, this),
|
||||||
false, program.memsizer, target.position
|
false, program.memsizer, fcall.position
|
||||||
)
|
)
|
||||||
translateNormalAssignment(assignArgument)
|
translateNormalAssignment(assignArgument)
|
||||||
} else {
|
} else {
|
||||||
@ -2892,24 +2901,24 @@ $repeatLabel lda $counterVar
|
|||||||
else -> throw AssemblyError("invalid dt")
|
else -> throw AssemblyError("invalid dt")
|
||||||
}
|
}
|
||||||
AsmAssignment(
|
AsmAssignment(
|
||||||
singleArg,
|
firstArg,
|
||||||
AsmAssignTarget(TargetStorageKind.REGISTER, program, this, argDt, scope, register = paramReg),
|
AsmAssignTarget(TargetStorageKind.REGISTER, program, this, argDt, scope, register = paramReg),
|
||||||
false, program.memsizer, target.position
|
false, program.memsizer, fcall.position
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// arg goes via parameter variable
|
// arg goes via parameter variable
|
||||||
val argVarName = asmVariableName(targetStmt.scopedName + targetStmt.parameters.single().name)
|
val argVarName = asmVariableName(targetStmt.scopedName + targetStmt.parameters.single().name)
|
||||||
AsmAssignment(
|
AsmAssignment(
|
||||||
singleArg,
|
firstArg,
|
||||||
AsmAssignTarget(TargetStorageKind.VARIABLE, program, this, argDt, scope, argVarName),
|
AsmAssignTarget(TargetStorageKind.VARIABLE, program, this, argDt, scope, argVarName),
|
||||||
false, program.memsizer, target.position
|
false, program.memsizer, fcall.position
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
translateNormalAssignment(assignArgument)
|
translateNormalAssignment(assignArgument)
|
||||||
}
|
}
|
||||||
if(targetStmt.shouldSaveX())
|
if(targetStmt.shouldSaveX())
|
||||||
saveRegisterLocal(CpuRegister.X, scope)
|
saveRegisterLocal(CpuRegister.X, scope)
|
||||||
out(" jsr ${asmSymbolName(target)}")
|
out(" jsr ${asmSymbolName(fcall.target)}")
|
||||||
if(targetStmt.shouldSaveX())
|
if(targetStmt.shouldSaveX())
|
||||||
restoreRegisterLocal(CpuRegister.X)
|
restoreRegisterLocal(CpuRegister.X)
|
||||||
return if(isStatement) DataType.UNDEFINED else targetStmt.returntypes.single()
|
return if(isStatement) DataType.UNDEFINED else targetStmt.returntypes.single()
|
||||||
|
@ -30,7 +30,8 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
|||||||
translateFunctioncall(fcall, func, discardResult = true, resultToStack = false, resultRegister = null)
|
translateFunctioncall(fcall, func, discardResult = true, resultToStack = false, resultRegister = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun translateUnaryFunctioncall(name: String, singleArg: AsmAssignSource, isStatement: Boolean, scope: Subroutine): DataType {
|
internal fun translateFunctionCallWithFirstArg(bfc: IFunctionCall, singleArg: AsmAssignSource, isStatement: Boolean, scope: Subroutine): DataType {
|
||||||
|
val name = bfc.target.nameInSource.single()
|
||||||
val func = BuiltinFunctions.getValue(name)
|
val func = BuiltinFunctions.getValue(name)
|
||||||
val argExpression =
|
val argExpression =
|
||||||
when(singleArg.kind) {
|
when(singleArg.kind) {
|
||||||
|
@ -158,8 +158,8 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
|
|||||||
when (target) {
|
when (target) {
|
||||||
is BuiltinFunctionPlaceholder -> {
|
is BuiltinFunctionPlaceholder -> {
|
||||||
val func = BuiltinFunctions.getValue(target.name)
|
val func = BuiltinFunctions.getValue(target.name)
|
||||||
if(func.parameters.size!=1)
|
if(func.parameters.isEmpty())
|
||||||
errors.err("can only use unary function", funccall.position)
|
errors.err("function must have at least one parameter", funccall.position)
|
||||||
else if(func.returnType==null && funccall !== segments.last())
|
else if(func.returnType==null && funccall !== segments.last())
|
||||||
errors.err("function must return a single value", funccall.position)
|
errors.err("function must return a single value", funccall.position)
|
||||||
|
|
||||||
@ -168,14 +168,12 @@ internal class VerifyFunctionArgTypes(val program: Program, val errors: IErrorRe
|
|||||||
errors.err("pipe value datatype $valueDt incompatible with function argument ${paramDts.toList()}", funccall.position)
|
errors.err("pipe value datatype $valueDt incompatible with function argument ${paramDts.toList()}", funccall.position)
|
||||||
|
|
||||||
if(errors.noErrors()) {
|
if(errors.noErrors()) {
|
||||||
// type can depend on the argument(s) of the function. For now, we only deal with unary functions,
|
|
||||||
// so we know there must be a single argument. Take its type from the previous expression in the pipe chain.
|
|
||||||
valueDt = builtinFunctionReturnType(func.name).getOrElse { DataType.UNDEFINED }
|
valueDt = builtinFunctionReturnType(func.name).getOrElse { DataType.UNDEFINED }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Subroutine -> {
|
is Subroutine -> {
|
||||||
if(target.parameters.size!=1)
|
if(target.parameters.isEmpty())
|
||||||
errors.err("can only use unary function", funccall.position)
|
errors.err("function must have at least one parameter", funccall.position)
|
||||||
else if(target.returntypes.size!=1 && funccall !== segments.last())
|
else if(target.returntypes.size!=1 && funccall !== segments.last())
|
||||||
errors.err("function must return a single value", funccall.position)
|
errors.err("function must return a single value", funccall.position)
|
||||||
|
|
||||||
|
@ -7,9 +7,17 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
|
sub add(ubyte first, ubyte second) -> ubyte {
|
||||||
|
return first+second
|
||||||
|
}
|
||||||
|
|
||||||
|
sub mul(ubyte first, ubyte second) -> ubyte {
|
||||||
|
return first*second
|
||||||
|
}
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte source=99
|
ubyte source=99
|
||||||
ubyte value= source |> math.sin8u() |> math.cos8u()
|
ubyte value = add(3,4) |> add(10) |> mul(2) |> math.sin8u() ; TODO should not work yet on vm codegen, but it compiles.... :/
|
||||||
txt.print_ub(value)
|
txt.print_ub(value)
|
||||||
|
|
||||||
; expected output: aaabbb aaa bbb
|
; expected output: aaabbb aaa bbb
|
||||||
|
Loading…
Reference in New Issue
Block a user