mirror of
https://github.com/irmen/prog8.git
synced 2024-12-26 14:29:35 +00:00
fix strlen
This commit is contained in:
parent
fe5b225732
commit
2ce6bc5946
@ -10,13 +10,13 @@ class SyntaxError(override var message: String, val position: Position) : AstExc
|
|||||||
override fun toString() = "$position Syntax error: $message"
|
override fun toString() = "$position Syntax error: $message"
|
||||||
}
|
}
|
||||||
|
|
||||||
class NameError(override var message: String, val position: Position) : AstException(message) {
|
open class NameError(override var message: String, val position: Position) : AstException(message) {
|
||||||
override fun toString() = "$position Name error: $message"
|
override fun toString() = "$position Name error: $message"
|
||||||
}
|
}
|
||||||
|
|
||||||
open class ExpressionError(message: String, val position: Position) : AstException(message) {
|
class ExpressionError(message: String, val position: Position) : AstException(message) {
|
||||||
override fun toString() = "$position Error: $message"
|
override fun toString() = "$position Error: $message"
|
||||||
}
|
}
|
||||||
|
|
||||||
class UndefinedSymbolError(symbol: IdentifierReference)
|
class UndefinedSymbolError(symbol: IdentifierReference)
|
||||||
: ExpressionError("undefined symbol: ${symbol.nameInSource.joinToString(".")}", symbol.position)
|
: NameError("undefined symbol: ${symbol.nameInSource.joinToString(".")}", symbol.position)
|
||||||
|
@ -326,7 +326,7 @@ class NumericLiteralValue(val type: DataType, // only numerical types allowed
|
|||||||
|
|
||||||
operator fun compareTo(other: NumericLiteralValue): Int = number.toDouble().compareTo(other.number.toDouble())
|
operator fun compareTo(other: NumericLiteralValue): Int = number.toDouble().compareTo(other.number.toDouble())
|
||||||
|
|
||||||
fun cast(targettype: DataType): NumericLiteralValue? {
|
fun cast(targettype: DataType): NumericLiteralValue {
|
||||||
if(type==targettype)
|
if(type==targettype)
|
||||||
return this
|
return this
|
||||||
val numval = number.toDouble()
|
val numval = number.toDouble()
|
||||||
@ -381,7 +381,7 @@ class NumericLiteralValue(val type: DataType, // only numerical types allowed
|
|||||||
}
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
return null // invalid type conversion from $this to $targettype
|
throw ExpressionError("can't cast $type into $targettype", position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,9 +848,12 @@ internal class AstChecker(private val program: Program,
|
|||||||
if(args.size!=func.parameters.size)
|
if(args.size!=func.parameters.size)
|
||||||
checkResult.add(SyntaxError("invalid number of arguments", position))
|
checkResult.add(SyntaxError("invalid number of arguments", position))
|
||||||
else {
|
else {
|
||||||
|
val paramTypesForAddressOf = PassByReferenceDatatypes + DataType.UWORD
|
||||||
for (arg in args.withIndex().zip(func.parameters)) {
|
for (arg in args.withIndex().zip(func.parameters)) {
|
||||||
val argDt=arg.first.value.inferType(program)
|
val argDt=arg.first.value.inferType(program)
|
||||||
if(argDt!=null && !(argDt isAssignableTo arg.second.possibleDatatypes)) {
|
if (argDt != null
|
||||||
|
&& !(argDt isAssignableTo arg.second.possibleDatatypes)
|
||||||
|
&& (argDt != DataType.UWORD || arg.second.possibleDatatypes.intersect(paramTypesForAddressOf).isEmpty())) {
|
||||||
checkResult.add(ExpressionError("builtin function '${target.name}' argument ${arg.first.index + 1} has invalid type $argDt, expected ${arg.second.possibleDatatypes}", position))
|
checkResult.add(ExpressionError("builtin function '${target.name}' argument ${arg.first.index + 1} has invalid type $argDt, expected ${arg.second.possibleDatatypes}", position))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -867,6 +870,14 @@ internal class AstChecker(private val program: Program,
|
|||||||
else if(dt1 !in NumericDatatypes)
|
else if(dt1 !in NumericDatatypes)
|
||||||
checkResult.add(ExpressionError("swap requires args of numerical type", position))
|
checkResult.add(ExpressionError("swap requires args of numerical type", position))
|
||||||
}
|
}
|
||||||
|
else if(target.name=="all" || target.name=="any") {
|
||||||
|
if((args[0] as? AddressOf)?.identifier?.targetVarDecl(program.namespace)?.datatype in StringDatatypes) {
|
||||||
|
checkResult.add(ExpressionError("any/all on a string is useless (is always true unless the string is empty)", position))
|
||||||
|
}
|
||||||
|
if(args[0].inferType(program) in StringDatatypes) {
|
||||||
|
checkResult.add(ExpressionError("any/all on a string is useless (is always true unless the string is empty)", position))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if(target is Subroutine) {
|
} else if(target is Subroutine) {
|
||||||
if(args.size!=target.parameters.size)
|
if(args.size!=target.parameters.size)
|
||||||
|
@ -381,7 +381,14 @@ internal fun fixupArrayDatatype(array: ReferenceLiteralValue, vardecl: VarDecl,
|
|||||||
val arrayDt = array.type
|
val arrayDt = array.type
|
||||||
if(arrayDt!=vardecl.datatype) {
|
if(arrayDt!=vardecl.datatype) {
|
||||||
// fix the datatype of the array (also on the heap) to match the vardecl
|
// fix the datatype of the array (also on the heap) to match the vardecl
|
||||||
val litval2 = array.cast(vardecl.datatype)!!
|
val litval2 =
|
||||||
|
try {
|
||||||
|
array.cast(vardecl.datatype)!!
|
||||||
|
} catch(x: ExpressionError) {
|
||||||
|
// couldn't cast permanently.
|
||||||
|
// instead, simply adjust the array type and trust the AstChecker to report the exact error
|
||||||
|
ReferenceLiteralValue(vardecl.datatype, null, array.array, array.heapId, array.position)
|
||||||
|
}
|
||||||
vardecl.value = litval2
|
vardecl.value = litval2
|
||||||
litval2.linkParents(vardecl)
|
litval2.linkParents(vardecl)
|
||||||
litval2.addToHeap(heap) // TODO is the previous array discarded from the resulting asm code?
|
litval2.addToHeap(heap) // TODO is the previous array discarded from the resulting asm code?
|
||||||
|
@ -135,10 +135,11 @@ internal class VarInitValueAndAddressOfCreator(private val program: Program): IA
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addAddressOfExprIfNeededForBuiltinFuncs(signature: FunctionSignature, args: MutableList<Expression>, parent: Statement) {
|
private fun addAddressOfExprIfNeededForBuiltinFuncs(signature: FunctionSignature, args: MutableList<Expression>, parent: Statement) {
|
||||||
|
// val paramTypesForAddressOf = PassByReferenceDatatypes + DataType.UWORD
|
||||||
for(arg in args.withIndex().zip(signature.parameters)) {
|
for(arg in args.withIndex().zip(signature.parameters)) {
|
||||||
val argvalue = arg.first.value
|
val argvalue = arg.first.value
|
||||||
val argDt = argvalue.inferType(program)
|
val argDt = argvalue.inferType(program)
|
||||||
if(DataType.UWORD in arg.second.possibleDatatypes && argDt in PassByReferenceDatatypes) {
|
if(argDt in PassByReferenceDatatypes && DataType.UWORD in arg.second.possibleDatatypes) {
|
||||||
if(argvalue !is IdentifierReference)
|
if(argvalue !is IdentifierReference)
|
||||||
throw CompilerException("pass-by-reference parameter isn't an identifier? $argvalue")
|
throw CompilerException("pass-by-reference parameter isn't an identifier? $argvalue")
|
||||||
val addrOf = AddressOf(argvalue, argvalue.position)
|
val addrOf = AddressOf(argvalue, argvalue.position)
|
||||||
|
@ -11,6 +11,7 @@ import prog8.ast.statements.AssignTarget
|
|||||||
import prog8.ast.statements.FunctionCallStatement
|
import prog8.ast.statements.FunctionCallStatement
|
||||||
import prog8.compiler.CompilationOptions
|
import prog8.compiler.CompilationOptions
|
||||||
import prog8.compiler.Zeropage
|
import prog8.compiler.Zeropage
|
||||||
|
import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_HEX
|
||||||
import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_PLUS1_HEX
|
import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_PLUS1_HEX
|
||||||
import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_HEX
|
import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_HEX
|
||||||
import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_PLUS1_HEX
|
import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_PLUS1_HEX
|
||||||
@ -79,7 +80,18 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
|||||||
asmgen.assignFromEvalResult(firstTarget)
|
asmgen.assignFromEvalResult(firstTarget)
|
||||||
asmgen.assignFromEvalResult(secondTarget)
|
asmgen.assignFromEvalResult(secondTarget)
|
||||||
}
|
}
|
||||||
// TODO: any(f), all(f), max(f), min(f), sum(f)
|
"strlen" -> {
|
||||||
|
val identifierName = asmgen.asmIdentifierName(fcall.arglist[0] as IdentifierReference)
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<$identifierName
|
||||||
|
sta $ESTACK_LO_HEX,x
|
||||||
|
lda #>$identifierName
|
||||||
|
sta $ESTACK_HI_HEX,x
|
||||||
|
dex
|
||||||
|
jsr prog8_lib.func_strlen
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
// TODO: any(f), all(f), max(f), min(f), sum(f), avg(f)
|
||||||
"sin", "cos", "tan", "atan",
|
"sin", "cos", "tan", "atan",
|
||||||
"ln", "log2", "sqrt", "rad",
|
"ln", "log2", "sqrt", "rad",
|
||||||
"deg", "round", "floor", "ceil",
|
"deg", "round", "floor", "ceil",
|
||||||
|
@ -1,17 +1,47 @@
|
|||||||
%import c64lib
|
%import c64lib
|
||||||
%import c64utils
|
%import c64utils
|
||||||
|
%import c64flt
|
||||||
|
%zeropage dontuse
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
A = testsub(33)
|
byte[] barr = [-100, 0, 99, -122, 22]
|
||||||
}
|
ubyte[] ubarr = [100, 0, 99, 199, 22]
|
||||||
|
word[] warr = [-1000, 0, 999, -4444, 222]
|
||||||
|
uword[] uwarr = [1000, 0, 222, 4444, 999]
|
||||||
|
float[] farr = [-1000.1, 0, 999.9, -4444.4, 222.2]
|
||||||
|
str name = "irmen"
|
||||||
|
ubyte ub
|
||||||
|
byte bb
|
||||||
|
word ww
|
||||||
|
uword uw
|
||||||
|
float ff
|
||||||
|
|
||||||
asmsub testsub(ubyte foo @stack) -> ubyte @stack {
|
; LEN/STRLEN
|
||||||
%asm {{
|
ubyte length = len(name)
|
||||||
Y=44
|
if(length!=5) c64scr.print("error len1\n")
|
||||||
rts
|
length = len(uwarr)
|
||||||
}}
|
if(length!=5) c64scr.print("error len2\n")
|
||||||
}
|
length=strlen(name)
|
||||||
|
if(length!=5) c64scr.print("error strlen1\n")
|
||||||
|
name[3] = 0
|
||||||
|
length=strlen(name)
|
||||||
|
if(length!=3) c64scr.print("error strlen2\n")
|
||||||
|
|
||||||
|
; MAX
|
||||||
|
; ub = max(ubarr)
|
||||||
|
; bb = max(barr)
|
||||||
|
; ww = max(warr)
|
||||||
|
; uw = max(uwarr)
|
||||||
|
; ff = max(farr)
|
||||||
|
|
||||||
|
; word ww = sum(barr)
|
||||||
|
; uword uw = sum(ubarr)
|
||||||
|
; ww = sum(warr)
|
||||||
|
; uw = sum(uwarr)
|
||||||
|
; float ff = sum(farr)
|
||||||
|
|
||||||
|
c64scr.print("\nyou should see no errors above.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user