mirror of
https://github.com/irmen/prog8.git
synced 2024-08-20 05:29:02 +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"
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
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())
|
||||
|
||||
fun cast(targettype: DataType): NumericLiteralValue? {
|
||||
fun cast(targettype: DataType): NumericLiteralValue {
|
||||
if(type==targettype)
|
||||
return this
|
||||
val numval = number.toDouble()
|
||||
@ -381,7 +381,7 @@ class NumericLiteralValue(val type: DataType, // only numerical types allowed
|
||||
}
|
||||
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)
|
||||
checkResult.add(SyntaxError("invalid number of arguments", position))
|
||||
else {
|
||||
val paramTypesForAddressOf = PassByReferenceDatatypes + DataType.UWORD
|
||||
for (arg in args.withIndex().zip(func.parameters)) {
|
||||
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))
|
||||
}
|
||||
}
|
||||
@ -867,6 +870,14 @@ internal class AstChecker(private val program: Program,
|
||||
else if(dt1 !in NumericDatatypes)
|
||||
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) {
|
||||
if(args.size!=target.parameters.size)
|
||||
|
@ -381,7 +381,14 @@ internal fun fixupArrayDatatype(array: ReferenceLiteralValue, vardecl: VarDecl,
|
||||
val arrayDt = array.type
|
||||
if(arrayDt!=vardecl.datatype) {
|
||||
// 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
|
||||
litval2.linkParents(vardecl)
|
||||
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) {
|
||||
// val paramTypesForAddressOf = PassByReferenceDatatypes + DataType.UWORD
|
||||
for(arg in args.withIndex().zip(signature.parameters)) {
|
||||
val argvalue = arg.first.value
|
||||
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)
|
||||
throw CompilerException("pass-by-reference parameter isn't an identifier? $argvalue")
|
||||
val addrOf = AddressOf(argvalue, argvalue.position)
|
||||
|
@ -11,6 +11,7 @@ import prog8.ast.statements.AssignTarget
|
||||
import prog8.ast.statements.FunctionCallStatement
|
||||
import prog8.compiler.CompilationOptions
|
||||
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_LO_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(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",
|
||||
"ln", "log2", "sqrt", "rad",
|
||||
"deg", "round", "floor", "ceil",
|
||||
|
@ -1,17 +1,47 @@
|
||||
%import c64lib
|
||||
%import c64utils
|
||||
%import c64flt
|
||||
%zeropage dontuse
|
||||
|
||||
main {
|
||||
|
||||
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 {
|
||||
%asm {{
|
||||
Y=44
|
||||
rts
|
||||
}}
|
||||
}
|
||||
; LEN/STRLEN
|
||||
ubyte length = len(name)
|
||||
if(length!=5) c64scr.print("error len1\n")
|
||||
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