mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +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
|
||||
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.
|
||||
|
||||
|
||||
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 {
|
||||
;memory byte derp = $ffdd
|
||||
;memory byte derp2 = 2+$ffdd+sin(3)
|
||||
memory byte derp3 = round(sin(3))
|
||||
memory byte derp = max($ffdd)
|
||||
memory byte derpA = abs(-2.5-0.5)
|
||||
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 hopla2=100+(-main.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? {
|
||||
// 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
|
||||
return when(location.scopedName[0]){
|
||||
"sin" -> builtin_sin(arglist, namespace)
|
||||
@ -541,6 +540,8 @@ data class FunctionCall(var location: Identifier, var arglist: List<IExpression>
|
||||
"max" -> builtin_max(arglist, namespace)
|
||||
"min" -> builtin_min(arglist, namespace)
|
||||
"round" -> builtin_round(arglist, namespace)
|
||||
"rad" -> builtin_rad(arglist, namespace)
|
||||
"deg" -> builtin_deg(arglist, namespace)
|
||||
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
|
||||
*/
|
||||
override fun process(identifier: Identifier): IExpression {
|
||||
println("PROCESS ID $identifier") // todo
|
||||
val const = identifier.constValue(globalNamespace)
|
||||
return const ?: identifier
|
||||
return identifier.constValue(globalNamespace) ?: 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.INameScope
|
||||
import il65.ast.LiteralValue
|
||||
import il65.ast.Position
|
||||
|
||||
private fun oneDoubleArg(args: List<IExpression>, namespace: INameScope, function: (arg: Double)->Double): LiteralValue {
|
||||
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_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_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_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)
|
||||
@ -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_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_max(args: List<IExpression>, namespace: INameScope): LiteralValue = twoDoubleArg(args, namespace, Math::max)
|
||||
fun builtin_min(args: List<IExpression>, namespace: INameScope): LiteralValue = twoDoubleArg(args, namespace, Math::min)
|
||||
fun builtin_rad(args: List<IExpression>, namespace: INameScope): LiteralValue = oneDoubleArg(args, namespace, Math::toRadians)
|
||||
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