mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
functions
This commit is contained in:
parent
74fd5d29b8
commit
666b9b2263
@ -360,3 +360,54 @@ by nothing, which is the same as AXY) to tell the compiler you want to preserve
|
|||||||
value of the given registers after the subroutine call. Otherwise, the subroutine may just
|
value of the given registers after the subroutine call. Otherwise, the subroutine may just
|
||||||
as well clobber all three registers. Preserving the original values does result in some
|
as well clobber all three registers. Preserving the original values does result in some
|
||||||
stack manipulation code to be inserted for every call like this, which can be quite slow.
|
stack manipulation code to be inserted for every call like this, which can be quite slow.
|
||||||
|
|
||||||
|
|
||||||
|
Built-in Functions
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The compiler has the following built-in functions that you can use in expressions:
|
||||||
|
|
||||||
|
sin(value)
|
||||||
|
Sine.
|
||||||
|
|
||||||
|
cos(value)
|
||||||
|
Cosine.
|
||||||
|
|
||||||
|
abs(value)
|
||||||
|
Absolute value.
|
||||||
|
|
||||||
|
acos(value)
|
||||||
|
Arccosine.
|
||||||
|
|
||||||
|
asin(value)
|
||||||
|
Arcsine.
|
||||||
|
|
||||||
|
tan(value)
|
||||||
|
Tangent.
|
||||||
|
|
||||||
|
atan(value)
|
||||||
|
Arctangent.
|
||||||
|
|
||||||
|
log(value)
|
||||||
|
Natural logarithm.
|
||||||
|
|
||||||
|
log10(value)
|
||||||
|
Base-10 logarithm.
|
||||||
|
|
||||||
|
sqrt(value)
|
||||||
|
Square root.
|
||||||
|
|
||||||
|
max(value [, value, ...])
|
||||||
|
Maximum of the values.
|
||||||
|
|
||||||
|
min(value [, value, ...])
|
||||||
|
Minumum of the values.
|
||||||
|
|
||||||
|
round(value)
|
||||||
|
Rounds the floating point to an integer.
|
||||||
|
|
||||||
|
rad(value)
|
||||||
|
Degrees to radians.
|
||||||
|
|
||||||
|
deg(value)
|
||||||
|
Radians to degrees.
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
~ main $c003 {
|
~ main $c003 {
|
||||||
;memory byte derp = $ffdd
|
memory byte derp = max($ffdd)
|
||||||
;memory byte derp2 = 2+$ffdd+sin(3)
|
memory byte derpA = abs(-2.5-0.5)
|
||||||
memory byte derp3 = round(sin(3))
|
memory byte derpB = max(1, 2.2, 4.4, 100)
|
||||||
|
memory byte cderp = min($ffdd)
|
||||||
|
memory byte cderpA = min($ffdd, 10, 20, 30)
|
||||||
|
memory byte cderpB = min(1, 2.2, 4.4, 100)
|
||||||
|
memory byte derp2 = 2+$ffdd+round(10*sin(3))
|
||||||
|
memory byte derp3 = round(100*sin(3))
|
||||||
const byte hopla=55-33
|
const byte hopla=55-33
|
||||||
const byte hopla2=100+(-main.hopla)
|
const byte hopla2=100+(-main.hopla)
|
||||||
const byte hopla3=100+(-hopla)
|
const byte hopla3=100+(-hopla)
|
||||||
|
@ -525,7 +525,6 @@ data class FunctionCall(var location: Identifier, var arglist: List<IExpression>
|
|||||||
|
|
||||||
override fun constValue(namespace: INameScope): LiteralValue? {
|
override fun constValue(namespace: INameScope): LiteralValue? {
|
||||||
// if the function is a built-in function and the args are consts, should evaluate!
|
// if the function is a built-in function and the args are consts, should evaluate!
|
||||||
println("CONSTVALUE of Function call $location") // todo
|
|
||||||
if(location.scopedName.size>1) return null
|
if(location.scopedName.size>1) return null
|
||||||
return when(location.scopedName[0]){
|
return when(location.scopedName[0]){
|
||||||
"sin" -> builtin_sin(arglist, namespace)
|
"sin" -> builtin_sin(arglist, namespace)
|
||||||
@ -541,6 +540,8 @@ data class FunctionCall(var location: Identifier, var arglist: List<IExpression>
|
|||||||
"max" -> builtin_max(arglist, namespace)
|
"max" -> builtin_max(arglist, namespace)
|
||||||
"min" -> builtin_min(arglist, namespace)
|
"min" -> builtin_min(arglist, namespace)
|
||||||
"round" -> builtin_round(arglist, namespace)
|
"round" -> builtin_round(arglist, namespace)
|
||||||
|
"rad" -> builtin_rad(arglist, namespace)
|
||||||
|
"deg" -> builtin_deg(arglist, namespace)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,12 @@ class AstOptimizer(private val globalNamespace: INameScope) : IAstProcessor {
|
|||||||
* some identifiers can be replaced with the constant value they refer to
|
* some identifiers can be replaced with the constant value they refer to
|
||||||
*/
|
*/
|
||||||
override fun process(identifier: Identifier): IExpression {
|
override fun process(identifier: Identifier): IExpression {
|
||||||
println("PROCESS ID $identifier") // todo
|
return identifier.constValue(globalNamespace) ?: identifier
|
||||||
val const = identifier.constValue(globalNamespace)
|
}
|
||||||
return const ?: identifier
|
|
||||||
|
override fun process(functionCall: FunctionCall): IExpression {
|
||||||
|
super.process(functionCall)
|
||||||
|
return functionCall.constValue(globalNamespace) ?: functionCall
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,6 +3,7 @@ package il65.functions
|
|||||||
import il65.ast.IExpression
|
import il65.ast.IExpression
|
||||||
import il65.ast.INameScope
|
import il65.ast.INameScope
|
||||||
import il65.ast.LiteralValue
|
import il65.ast.LiteralValue
|
||||||
|
import il65.ast.Position
|
||||||
|
|
||||||
private fun oneDoubleArg(args: List<IExpression>, namespace: INameScope, function: (arg: Double)->Double): LiteralValue {
|
private fun oneDoubleArg(args: List<IExpression>, namespace: INameScope, function: (arg: Double)->Double): LiteralValue {
|
||||||
if(args.size!=1)
|
if(args.size!=1)
|
||||||
@ -50,7 +51,6 @@ private fun twoDoubleArg(args: List<IExpression>, namespace: INameScope, functio
|
|||||||
fun builtin_round(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArgOutputInt(args, namespace) { it -> Math.round(it).toInt() }
|
fun builtin_round(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArgOutputInt(args, namespace) { it -> Math.round(it).toInt() }
|
||||||
fun builtin_sin(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::sin)
|
fun builtin_sin(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::sin)
|
||||||
fun builtin_cos(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::cos)
|
fun builtin_cos(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::cos)
|
||||||
fun builtin_abs(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::abs)
|
|
||||||
fun builtin_acos(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::acos)
|
fun builtin_acos(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::acos)
|
||||||
fun builtin_asin(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::asin)
|
fun builtin_asin(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::asin)
|
||||||
fun builtin_tan(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::tan)
|
fun builtin_tan(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::tan)
|
||||||
@ -58,5 +58,46 @@ fun builtin_atan(args: List<IExpression>, namespace: INameScope): LiteralValue =
|
|||||||
fun builtin_log(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::log)
|
fun builtin_log(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::log)
|
||||||
fun builtin_log10(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::log10)
|
fun builtin_log10(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::log10)
|
||||||
fun builtin_sqrt(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::sqrt)
|
fun builtin_sqrt(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::sqrt)
|
||||||
fun builtin_max(args: List<IExpression>, namespace: INameScope): LiteralValue = twoDoubleArg(args, namespace, Math::max)
|
fun builtin_rad(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::toRadians)
|
||||||
fun builtin_min(args: List<IExpression>, namespace: INameScope): LiteralValue = twoDoubleArg(args, namespace, Math::min)
|
fun builtin_deg(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::toDegrees)
|
||||||
|
|
||||||
|
fun builtin_abs(args: List<IExpression>, namespace: INameScope): LiteralValue {
|
||||||
|
if(args.size!=1)
|
||||||
|
throw UnsupportedOperationException("built-in function abs requires one numeric argument")
|
||||||
|
val float = args[0].constValue(namespace)?.asFloat()
|
||||||
|
if(float!=null)
|
||||||
|
return IntOrFloatLiteral(Math.abs(float), args[0].position)
|
||||||
|
else
|
||||||
|
throw UnsupportedOperationException("built-in function abs requires floating point value as argument")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun builtin_max(args: List<IExpression>, namespace: INameScope): LiteralValue {
|
||||||
|
if(args.isEmpty())
|
||||||
|
throw UnsupportedOperationException("max requires at least one argument")
|
||||||
|
val constants = args.map { it.constValue(namespace) }
|
||||||
|
if(constants.contains(null))
|
||||||
|
throw UnsupportedOperationException("not all arguments to max are a constant value")
|
||||||
|
val result = constants.map { it?.asFloat()!! }.max()
|
||||||
|
return IntOrFloatLiteral(result!!, args[0].position)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun builtin_min(args: List<IExpression>, namespace: INameScope): LiteralValue {
|
||||||
|
if(args.isEmpty())
|
||||||
|
throw UnsupportedOperationException("min requires at least one argument")
|
||||||
|
val constants = args.map { it.constValue(namespace) }
|
||||||
|
if(constants.contains(null))
|
||||||
|
throw UnsupportedOperationException("not all arguments to min are a constant value")
|
||||||
|
val result = constants.map { it?.asFloat()!! }.min()
|
||||||
|
return IntOrFloatLiteral(result!!, args[0].position)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun IntOrFloatLiteral(value: Double, position: Position?): LiteralValue {
|
||||||
|
val intresult = value.toInt()
|
||||||
|
val result = if(value-intresult==0.0)
|
||||||
|
LiteralValue(intvalue = intresult)
|
||||||
|
else
|
||||||
|
LiteralValue(floatvalue = value)
|
||||||
|
result.position = position
|
||||||
|
return result
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user