mirror of
https://github.com/irmen/prog8.git
synced 2025-11-01 06:16:15 +00:00
trying to fix arithmetic and funcion calls
This commit is contained in:
@@ -97,14 +97,13 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
|
|||||||
val leftDt = left.inferType(program)
|
val leftDt = left.inferType(program)
|
||||||
val rightDt = right.inferType(program)
|
val rightDt = right.inferType(program)
|
||||||
return when (operator) {
|
return when (operator) {
|
||||||
"+", "-", "*", "**", "%" -> if (leftDt == null || rightDt == null) null else {
|
"+", "-", "*", "**", "%", "/" -> if (leftDt == null || rightDt == null) null else {
|
||||||
try {
|
try {
|
||||||
arithmeticOpDt(leftDt, rightDt)
|
commonDatatype(leftDt, rightDt, null, null).first
|
||||||
} catch (x: FatalAstException) {
|
} catch (x: FatalAstException) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"/" -> if (leftDt == null || rightDt == null) null else divisionOpDt(leftDt, rightDt)
|
|
||||||
"&" -> leftDt
|
"&" -> leftDt
|
||||||
"|" -> leftDt
|
"|" -> leftDt
|
||||||
"^" -> leftDt
|
"^" -> leftDt
|
||||||
@@ -118,86 +117,14 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun divisionOpDt(leftDt: DataType, rightDt: DataType): DataType {
|
|
||||||
return when (leftDt) {
|
|
||||||
DataType.UBYTE -> when (rightDt) {
|
|
||||||
DataType.UBYTE, DataType.UWORD -> DataType.UBYTE
|
|
||||||
DataType.BYTE, DataType.WORD -> DataType.WORD
|
|
||||||
DataType.FLOAT -> DataType.BYTE
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
DataType.BYTE -> when (rightDt) {
|
|
||||||
in NumericDatatypes -> DataType.BYTE
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
DataType.UWORD -> when (rightDt) {
|
|
||||||
DataType.UBYTE, DataType.UWORD -> DataType.UWORD
|
|
||||||
DataType.BYTE, DataType.WORD -> DataType.WORD
|
|
||||||
DataType.FLOAT -> DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
DataType.WORD -> when (rightDt) {
|
|
||||||
in NumericDatatypes -> DataType.WORD
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
DataType.FLOAT -> when (rightDt) {
|
|
||||||
in NumericDatatypes -> DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun arithmeticOpDt(leftDt: DataType, rightDt: DataType): DataType {
|
|
||||||
return when (leftDt) {
|
|
||||||
DataType.UBYTE -> when (rightDt) {
|
|
||||||
DataType.UBYTE -> DataType.UBYTE
|
|
||||||
DataType.BYTE -> DataType.BYTE
|
|
||||||
DataType.UWORD -> DataType.UWORD
|
|
||||||
DataType.WORD -> DataType.WORD
|
|
||||||
DataType.FLOAT -> DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
DataType.BYTE -> when (rightDt) {
|
|
||||||
in ByteDatatypes -> DataType.BYTE
|
|
||||||
in WordDatatypes -> DataType.WORD
|
|
||||||
DataType.FLOAT -> DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
DataType.UWORD -> when (rightDt) {
|
|
||||||
DataType.UBYTE, DataType.UWORD -> DataType.UWORD
|
|
||||||
DataType.BYTE, DataType.WORD -> DataType.WORD
|
|
||||||
DataType.FLOAT -> DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
DataType.WORD -> when (rightDt) {
|
|
||||||
in IntegerDatatypes -> DataType.WORD
|
|
||||||
DataType.FLOAT -> DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
DataType.FLOAT -> when (rightDt) {
|
|
||||||
in NumericDatatypes -> DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
else -> throw FatalAstException("arithmetic operation on incompatible datatypes: $leftDt and $rightDt")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun commonDatatype(leftDt: DataType, rightDt: DataType,
|
fun commonDatatype(leftDt: DataType, rightDt: DataType,
|
||||||
left: Expression, right: Expression): Pair<DataType, Expression?> {
|
left: Expression?, right: Expression?): Pair<DataType, Expression?> {
|
||||||
// byte + byte -> byte
|
// byte + byte -> byte
|
||||||
// byte + word -> word
|
// byte + word -> word
|
||||||
// word + byte -> word
|
// word + byte -> word
|
||||||
// word + word -> word
|
// word + word -> word
|
||||||
// a combination with a float will be float (but give a warning about this!)
|
// a combination with a float will be float (but give a warning about this!)
|
||||||
|
|
||||||
if(this.operator=="/") {
|
|
||||||
// division is a bit weird, don't cast the operands
|
|
||||||
val commondt = divisionOpDt(leftDt, rightDt)
|
|
||||||
return Pair(commondt, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
return when (leftDt) {
|
return when (leftDt) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
when (rightDt) {
|
when (rightDt) {
|
||||||
@@ -222,7 +149,7 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
|
|||||||
DataType.UWORD -> {
|
DataType.UWORD -> {
|
||||||
when (rightDt) {
|
when (rightDt) {
|
||||||
DataType.UBYTE -> Pair(DataType.UWORD, right)
|
DataType.UBYTE -> Pair(DataType.UWORD, right)
|
||||||
DataType.BYTE -> Pair(DataType.UWORD, right)
|
DataType.BYTE -> Pair(DataType.WORD, right)
|
||||||
DataType.UWORD -> Pair(DataType.UWORD, null)
|
DataType.UWORD -> Pair(DataType.UWORD, null)
|
||||||
DataType.WORD -> Pair(DataType.WORD, left)
|
DataType.WORD -> Pair(DataType.WORD, left)
|
||||||
DataType.FLOAT -> Pair(DataType.FLOAT, left)
|
DataType.FLOAT -> Pair(DataType.FLOAT, left)
|
||||||
@@ -246,6 +173,7 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ArrayIndexedExpression(var identifier: IdentifierReference,
|
class ArrayIndexedExpression(var identifier: IdentifierReference,
|
||||||
val arrayspec: ArrayIndex,
|
val arrayspec: ArrayIndex,
|
||||||
|
|||||||
@@ -762,6 +762,8 @@ internal class AstChecker(private val program: Program,
|
|||||||
checkResult.add(ExpressionError("left operand is not numeric", expr.left.position))
|
checkResult.add(ExpressionError("left operand is not numeric", expr.left.position))
|
||||||
if(rightDt!in NumericDatatypes)
|
if(rightDt!in NumericDatatypes)
|
||||||
checkResult.add(ExpressionError("right operand is not numeric", expr.right.position))
|
checkResult.add(ExpressionError("right operand is not numeric", expr.right.position))
|
||||||
|
if(leftDt!=rightDt)
|
||||||
|
checkResult.add(ExpressionError("left and right operands aren't the same type", expr.left.position))
|
||||||
super.visit(expr)
|
super.visit(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -187,26 +187,29 @@ internal class StatementReorderer(private val program: Program): IAstModifyingVi
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(expr: BinaryExpression): Expression {
|
override fun visit(expr: BinaryExpression): Expression {
|
||||||
val leftDt = expr.left.inferType(program)
|
val expr2 = super.visit(expr)
|
||||||
val rightDt = expr.right.inferType(program)
|
if(expr2 !is BinaryExpression)
|
||||||
|
return expr2
|
||||||
|
val leftDt = expr2.left.inferType(program)
|
||||||
|
val rightDt = expr2.right.inferType(program)
|
||||||
if(leftDt!=null && rightDt!=null && leftDt!=rightDt) {
|
if(leftDt!=null && rightDt!=null && leftDt!=rightDt) {
|
||||||
// determine common datatype and add typecast as required to make left and right equal types
|
// determine common datatype and add typecast as required to make left and right equal types
|
||||||
val (commonDt, toFix) = expr.commonDatatype(leftDt, rightDt, expr.left, expr.right)
|
val (commonDt, toFix) = BinaryExpression.commonDatatype(leftDt, rightDt, expr2.left, expr2.right)
|
||||||
if(toFix!=null) {
|
if(toFix!=null) {
|
||||||
when {
|
when {
|
||||||
toFix===expr.left -> {
|
toFix===expr2.left -> {
|
||||||
expr.left = TypecastExpression(expr.left, commonDt, true, expr.left.position)
|
expr2.left = TypecastExpression(expr2.left, commonDt, true, expr2.left.position)
|
||||||
expr.left.linkParents(expr)
|
expr2.left.linkParents(expr2)
|
||||||
}
|
}
|
||||||
toFix===expr.right -> {
|
toFix===expr2.right -> {
|
||||||
expr.right = TypecastExpression(expr.right, commonDt, true, expr.right.position)
|
expr2.right = TypecastExpression(expr2.right, commonDt, true, expr2.right.position)
|
||||||
expr.right.linkParents(expr)
|
expr2.right.linkParents(expr2)
|
||||||
}
|
}
|
||||||
else -> throw FatalAstException("confused binary expression side")
|
else -> throw FatalAstException("confused binary expression side")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.visit(expr)
|
return expr2
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(assignment: Assignment): Statement {
|
override fun visit(assignment: Assignment): Statement {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import prog8.ast.processing.IAstModifyingVisitor
|
|||||||
import prog8.ast.statements.AnonymousScope
|
import prog8.ast.statements.AnonymousScope
|
||||||
import prog8.ast.statements.Statement
|
import prog8.ast.statements.Statement
|
||||||
import prog8.ast.statements.VarDecl
|
import prog8.ast.statements.VarDecl
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class AnonymousScopeVarsCleanup(val program: Program): IAstModifyingVisitor {
|
class AnonymousScopeVarsCleanup(val program: Program): IAstModifyingVisitor {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -32,8 +33,12 @@ class AnonymousScopeVarsCleanup(val program: Program): IAstModifyingVisitor {
|
|||||||
|
|
||||||
private val varsToMove: MutableMap<AnonymousScope, List<VarDecl>> = mutableMapOf()
|
private val varsToMove: MutableMap<AnonymousScope, List<VarDecl>> = mutableMapOf()
|
||||||
|
|
||||||
|
private val currentAnonScope: Stack<AnonymousScope> = Stack()
|
||||||
|
|
||||||
override fun visit(scope: AnonymousScope): Statement {
|
override fun visit(scope: AnonymousScope): Statement {
|
||||||
|
currentAnonScope.push(scope)
|
||||||
val scope2 = super.visit(scope) as AnonymousScope
|
val scope2 = super.visit(scope) as AnonymousScope
|
||||||
|
currentAnonScope.pop()
|
||||||
val vardecls = scope2.statements.filterIsInstance<VarDecl>()
|
val vardecls = scope2.statements.filterIsInstance<VarDecl>()
|
||||||
varsToMove[scope2] = vardecls
|
varsToMove[scope2] = vardecls
|
||||||
return scope2
|
return scope2
|
||||||
@@ -43,26 +48,35 @@ class AnonymousScopeVarsCleanup(val program: Program): IAstModifyingVisitor {
|
|||||||
|
|
||||||
override fun visit(decl: VarDecl): Statement {
|
override fun visit(decl: VarDecl): Statement {
|
||||||
val decl2 = super.visit(decl) as VarDecl
|
val decl2 = super.visit(decl) as VarDecl
|
||||||
val scope = decl2.definingScope()
|
if(currentAnonScope.isEmpty())
|
||||||
if(scope is AnonymousScope) {
|
|
||||||
return decl2.withPrefixedName(nameprefix(scope))
|
|
||||||
}
|
|
||||||
return decl2
|
return decl2
|
||||||
|
return decl2.withPrefixedName(nameprefix(currentAnonScope.peek()))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(identifier: IdentifierReference): Expression {
|
override fun visit(identifier: IdentifierReference): Expression {
|
||||||
val ident = super.visit(identifier)
|
val ident = super.visit(identifier)
|
||||||
if(ident !is IdentifierReference)
|
if(ident !is IdentifierReference)
|
||||||
return ident
|
return ident
|
||||||
|
if(currentAnonScope.isEmpty())
|
||||||
val scope = ident.definingScope() as? AnonymousScope ?: return ident
|
return ident
|
||||||
val vardecl = ident.targetVarDecl(program.namespace)
|
val vardecl = ident.targetVarDecl(program.namespace)
|
||||||
return if(vardecl!=null && vardecl.definingScope() == ident.definingScope()) {
|
return if(vardecl!=null && vardecl.definingScope() === ident.definingScope()) {
|
||||||
// prefix the variable name reference that is defined inside the anon scope
|
// prefix the variable name reference that is defined inside the anon scope
|
||||||
ident.withPrefixedName(nameprefix(scope))
|
ident.withPrefixedName(nameprefix(currentAnonScope.peek()))
|
||||||
} else {
|
} else {
|
||||||
ident
|
ident
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
; @todo FIX Symbol lookup over anon scopes
|
||||||
|
; sub start() {
|
||||||
|
; for ubyte i in 0 to 10 {
|
||||||
|
; word rz = 4
|
||||||
|
; if rz >= 1 {
|
||||||
|
; word persp = rz+1
|
||||||
|
; }
|
||||||
|
; }
|
||||||
|
; }
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1823,6 +1823,9 @@ $endLabel""")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: use optimized routines such as mul_10
|
||||||
|
|
||||||
|
|
||||||
private fun translateBinaryOperatorBytes(operator: String, types: DataType) {
|
private fun translateBinaryOperatorBytes(operator: String, types: DataType) {
|
||||||
when(operator) {
|
when(operator) {
|
||||||
"**" -> throw AssemblyError("** operator requires floats")
|
"**" -> throw AssemblyError("** operator requires floats")
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package prog8.compiler.target.c64.codegen2
|
|||||||
|
|
||||||
import prog8.ast.IFunctionCall
|
import prog8.ast.IFunctionCall
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
|
import prog8.ast.base.ByteDatatypes
|
||||||
|
import prog8.ast.base.DataType
|
||||||
import prog8.ast.base.WordDatatypes
|
import prog8.ast.base.WordDatatypes
|
||||||
import prog8.ast.expressions.Expression
|
import prog8.ast.expressions.Expression
|
||||||
import prog8.ast.expressions.FunctionCall
|
import prog8.ast.expressions.FunctionCall
|
||||||
@@ -56,6 +58,24 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
|||||||
translateFunctionArguments(fcall.arglist)
|
translateFunctionArguments(fcall.arglist)
|
||||||
asmgen.out(" inx | lda $ESTACK_LO_HEX,x | sta $ESTACK_HI_PLUS1_HEX,x")
|
asmgen.out(" inx | lda $ESTACK_LO_HEX,x | sta $ESTACK_HI_PLUS1_HEX,x")
|
||||||
}
|
}
|
||||||
|
"abs" -> {
|
||||||
|
translateFunctionArguments(fcall.arglist)
|
||||||
|
val dt = fcall.arglist.single().inferType(program)!!
|
||||||
|
when (dt) {
|
||||||
|
in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b")
|
||||||
|
in WordDatatypes -> asmgen.out(" jsr prog8_lib.abs_w")
|
||||||
|
DataType.FLOAT -> asmgen.out(" jsr c64flt.abs_f")
|
||||||
|
else -> throw AssemblyError("weird type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: any(f), all(f), max(f), min(f), sum(f)
|
||||||
|
"sin", "cos", "tan", "atan",
|
||||||
|
"ln", "log2", "sqrt", "rad",
|
||||||
|
"deg", "round", "floor", "ceil",
|
||||||
|
"rdnf" -> {
|
||||||
|
translateFunctionArguments(fcall.arglist)
|
||||||
|
asmgen.out(" jsr c64flt.func_$functionName")
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
translateFunctionArguments(fcall.arglist)
|
translateFunctionArguments(fcall.arglist)
|
||||||
asmgen.out(" jsr prog8_lib.func_$functionName")
|
asmgen.out(" jsr prog8_lib.func_$functionName")
|
||||||
|
|||||||
@@ -145,12 +145,11 @@ fun builtinFunctionReturnType(function: String, args: List<Expression>, program:
|
|||||||
|
|
||||||
return when (function) {
|
return when (function) {
|
||||||
"abs" -> {
|
"abs" -> {
|
||||||
when(val dt = args.single().inferType(program)) {
|
val dt = args.single().inferType(program)
|
||||||
in ByteDatatypes -> DataType.UBYTE
|
if(dt in NumericDatatypes)
|
||||||
in WordDatatypes -> DataType.UWORD
|
return dt
|
||||||
DataType.FLOAT -> DataType.FLOAT
|
else
|
||||||
else -> throw FatalAstException("weird datatype passed to abs $dt")
|
throw FatalAstException("weird datatype passed to abs $dt")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"max", "min" -> {
|
"max", "min" -> {
|
||||||
when(val dt = datatypeFromIterableArg(args.single())) {
|
when(val dt = datatypeFromIterableArg(args.single())) {
|
||||||
|
|||||||
@@ -107,8 +107,6 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
asBoolean = floatval != 0.0
|
asBoolean = floatval != 0.0
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
if(heapId==null)
|
|
||||||
throw IllegalArgumentException("for non-numeric types, a heapId should be given")
|
|
||||||
byteval = null
|
byteval = null
|
||||||
wordval = null
|
wordval = null
|
||||||
floatval = null
|
floatval = null
|
||||||
@@ -628,7 +626,7 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class RuntimeValueRange(type: DataType, val range: IntProgression): RuntimeValue(type, 0) {
|
class RuntimeValueRange(type: DataType, val range: IntProgression): RuntimeValue(type, array=range.toList().toTypedArray()) {
|
||||||
override fun iterator(): Iterator<Number> {
|
override fun iterator(): Iterator<Number> {
|
||||||
return range.iterator()
|
return range.iterator()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -675,23 +675,23 @@ class AstVm(val program: Program) {
|
|||||||
dialog.canvas.printText(args[0].wordval!!.toString(), true)
|
dialog.canvas.printText(args[0].wordval!!.toString(), true)
|
||||||
}
|
}
|
||||||
"c64scr.print_ubhex" -> {
|
"c64scr.print_ubhex" -> {
|
||||||
val prefix = if (args[0].asBoolean) "$" else ""
|
val number = args[0].byteval!!
|
||||||
val number = args[1].byteval!!
|
val prefix = if (args[1].asBoolean) "$" else ""
|
||||||
dialog.canvas.printText("$prefix${number.toString(16).padStart(2, '0')}", true)
|
dialog.canvas.printText("$prefix${number.toString(16).padStart(2, '0')}", true)
|
||||||
}
|
}
|
||||||
"c64scr.print_uwhex" -> {
|
"c64scr.print_uwhex" -> {
|
||||||
val prefix = if (args[0].asBoolean) "$" else ""
|
val number = args[0].wordval!!
|
||||||
val number = args[1].wordval!!
|
val prefix = if (args[1].asBoolean) "$" else ""
|
||||||
dialog.canvas.printText("$prefix${number.toString(16).padStart(4, '0')}", true)
|
dialog.canvas.printText("$prefix${number.toString(16).padStart(4, '0')}", true)
|
||||||
}
|
}
|
||||||
"c64scr.print_uwbin" -> {
|
"c64scr.print_uwbin" -> {
|
||||||
val prefix = if (args[0].asBoolean) "%" else ""
|
val number = args[0].wordval!!
|
||||||
val number = args[1].wordval!!
|
val prefix = if (args[1].asBoolean) "%" else ""
|
||||||
dialog.canvas.printText("$prefix${number.toString(2).padStart(16, '0')}", true)
|
dialog.canvas.printText("$prefix${number.toString(2).padStart(16, '0')}", true)
|
||||||
}
|
}
|
||||||
"c64scr.print_ubbin" -> {
|
"c64scr.print_ubbin" -> {
|
||||||
val prefix = if (args[0].asBoolean) "%" else ""
|
val number = args[0].byteval!!
|
||||||
val number = args[1].byteval!!
|
val prefix = if (args[1].asBoolean) "%" else ""
|
||||||
dialog.canvas.printText("$prefix${number.toString(2).padStart(8, '0')}", true)
|
dialog.canvas.printText("$prefix${number.toString(2).padStart(8, '0')}", true)
|
||||||
}
|
}
|
||||||
"c64scr.clear_screenchars" -> {
|
"c64scr.clear_screenchars" -> {
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ arithmetic: ``+`` ``-`` ``*`` ``/`` ``**`` ``%``
|
|||||||
``+``, ``-``, ``*``, ``/`` are the familiar arithmetic operations.
|
``+``, ``-``, ``*``, ``/`` are the familiar arithmetic operations.
|
||||||
``/`` is division (will result in integer division when using on integer operands, and a floating point division when at least one of the operands is a float)
|
``/`` is division (will result in integer division when using on integer operands, and a floating point division when at least one of the operands is a float)
|
||||||
``**`` is the power operator: ``3 ** 5`` is equal to 3*3*3*3*3 and is 243. (it only works on floating point variables)
|
``**`` is the power operator: ``3 ** 5`` is equal to 3*3*3*3*3 and is 243. (it only works on floating point variables)
|
||||||
``%`` is the remainder operator: ``25 % 7`` is 4. Be careful: without a space, %10 will be parsed as the binary number 2
|
``%`` is the remainder operator: ``25 % 7`` is 4. Be careful: without a space, %10 will be parsed as the binary number 2.
|
||||||
Remainder is only supported on integer operands (not floats).
|
Remainder is only supported on integer operands (not floats).
|
||||||
|
|
||||||
bitwise arithmetic: ``&`` ``|`` ``^`` ``~`` ``<<`` ``>>``
|
bitwise arithmetic: ``&`` ``|`` ``^`` ``~`` ``<<`` ``>>``
|
||||||
|
|||||||
@@ -1,36 +1,47 @@
|
|||||||
|
%import c64lib
|
||||||
|
%import c64utils
|
||||||
|
%import c64flt
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
c64.CHROUT('\n')
|
; float fl = 123.4567
|
||||||
%asm {{
|
; c64flt.print_f(round(fl))
|
||||||
stx $0410
|
; c64.CHROUT('\n')
|
||||||
}}
|
; c64flt.print_f(round(fl))
|
||||||
c64.CHRIN()
|
; c64.CHROUT('\n')
|
||||||
%asm {{
|
; c64flt.print_f(round(fl))
|
||||||
stx $0411
|
; c64.CHROUT('\n')
|
||||||
}}
|
; c64flt.print_f(ceil(fl))
|
||||||
print_notes(80,35)
|
; c64.CHROUT('\n')
|
||||||
%asm {{
|
; c64flt.print_f(ceil(fl))
|
||||||
stx $0412
|
; c64.CHROUT('\n')
|
||||||
}}
|
; c64flt.print_f(ceil(fl))
|
||||||
return
|
; c64.CHROUT('\n')
|
||||||
}
|
; c64flt.print_f(floor(fl))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64flt.print_f(floor(fl))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64flt.print_f(floor(fl))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; @($040a)=X
|
||||||
|
; return
|
||||||
|
|
||||||
sub print_notes(ubyte n1, ubyte n2) {
|
while true {
|
||||||
c64scr.print_ub(n1/2)
|
float clock_seconds = ((mkword(c64.TIME_LO, c64.TIME_MID) as float) + (c64.TIME_HI as float)*65536.0) / 60
|
||||||
c64.CHROUT('\n')
|
float hours = floor(clock_seconds / 3600)
|
||||||
c64scr.print_ub(n1/3)
|
clock_seconds -= hours*3600
|
||||||
c64.CHROUT('\n')
|
float minutes = floor(clock_seconds / 60)
|
||||||
c64scr.print_ub(n1/4)
|
clock_seconds = floor(clock_seconds - minutes * 60.0)
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64.CHROUT('\n')
|
c64scr.print("system time in ti$ is ")
|
||||||
c64scr.print_ub(n2/2)
|
c64flt.print_f(hours)
|
||||||
c64.CHROUT('\n')
|
c64.CHROUT(':')
|
||||||
c64scr.print_ub(n2/3)
|
c64flt.print_f(minutes)
|
||||||
c64.CHROUT('\n')
|
c64.CHROUT(':')
|
||||||
c64scr.print_ub(n2/4)
|
c64flt.print_f(clock_seconds)
|
||||||
c64.CHROUT('\n')
|
c64.CHROUT('\n')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user