Compare commits

...

2 Commits

Author SHA1 Message Date
aba122c3e6 math and docs 2025-06-04 09:02:08 +04:00
75d90d7228 shuttle operator <=> 2025-06-04 08:29:09 +04:00
8 changed files with 168 additions and 21 deletions

View File

@ -10,7 +10,7 @@ Same as in C++.
| 1 | `%` `*` `/` |
| 2 | `+` `-` |
| 3 | bit shifts (NI) |
| 4 | `<=>` (NI) |
| 4 | `<=>` (1) |
| 5 | `<=` `>=` `<` `>` |
| 6 | `==` `!=` |
| 7 | bitwise and `&` (NI) |
@ -18,7 +18,11 @@ Same as in C++.
| 10 | `&&` |
| 11<br/>lowest | `\|\|` |
- (NI) stands for not yet implemented.
(NI)
: not yet implemented.
(1)
: Shuttle operator: `a <=> b` returns 0 if a == b, negative Int if a < b and positive Int otherwise. It is necessary to override shuttle operator to make a class comparable.
## Operators
@ -43,22 +47,39 @@ or transformed `Real` otherwise.
| floor(x) | Computes the largest integer value not greater than x |
| ceil(x) | Computes the least integer value value not less than x |
| round(x) | Rounds x |
| | |
| abs(x) | absolute value, Int for integer x, Real otherwise |
| | |
## Scientific functions
## Mathematical functions
| name | meaning |
|---------------------|---------|
| `sin(x:Real): Real` | sine |
| | |
| | |
| | |
| name | meaning |
|-----------|------------------------------------------------------|
| sin(x) | sine |
| cos(x) | cosine |
| tan(x) | tangent |
| asin(x) | $sin^-1(x)$ |
| acos(x) | $cos^-1(x)$ |
| atan(x) | $tg^-1(x)$ |
| sinh(x) | hyperbolic sine |
| cosh(x) | hyperbolic cosine |
| tanh(x) | hyperbolic tangent |
| asinh(x) | $sinh^-1(x)$ |
| acosh(x) | $cosh^-1(x)$ |
| atanh(x) | $tgh^-1(x)$ |
| ln(x) | $ln(x)$, $ log_e(x) $ |
| exp(x) | $e^x$ |
| log10(x) | $log_{10}(x)$ |
| pow(x, y) | ${x^y}$ |
| sqrt(x) | $ \sqrt {x}$ |
| abs(x) | absolute value of x. Int if x is Int, Real otherwise |
For example:
sin(π/2)
>>> 1.0
For example:
assert( sin(π/2) == 1.0)
assert( cos(π/2) < 0.000001)
assert( abs(ln(exp(1))) - 1 < 0.00001)
>>> void
## Scientific constant

View File

@ -16,6 +16,9 @@ fun naiveCountHappyNumbers() {
count
}
//
// After all optimizations it takes ~120ms.
//
val found = naiveCountHappyNumbers()
println("Found happy numbers: "+found)
assert( found == 55252 )
assert( found == 55252 )

View File

@ -749,9 +749,9 @@ class Compiler(
var result: Obj = ObjVoid
val iVar = ObjInt(0)
loopVar.value = iVar
for( i in start ..< end) {
iVar.value = i.toLong()
if (catchBreak)
if( catchBreak) {
for (i in start..<end) {
iVar.value = i.toLong()
try {
result = body.execute(forContext)
} catch (lbe: LoopBreakContinueException) {
@ -760,7 +760,10 @@ class Compiler(
}
return lbe.result
}
else {
}
} else {
for (i in start.toLong()..<end.toLong()) {
iVar.value = i
result = body.execute(forContext)
}
}
@ -1181,6 +1184,8 @@ class Compiler(
Operator.simple(Token.Type.IS, lastPrty) { c, a, b -> ObjBool(a.isInstanceOf(b)) },
Operator.simple(Token.Type.NOTIS, lastPrty) { c, a, b -> ObjBool(!a.isInstanceOf(b)) },
// shuttle <=> 6
Operator.simple(Token.Type.SHUTTLE, ++lastPrty) { c, a, b ->
ObjInt(a.compareTo(c, b).toLong()) },
// bit shifts 7
Operator.simple(Token.Type.PLUS, ++lastPrty) { ctx, a, b -> a.plus(ctx, b) },
Operator.simple(Token.Type.MINUS, lastPrty) { ctx, a, b -> a.minus(ctx, b) },

View File

@ -153,7 +153,13 @@ private class Parser(fromPos: Pos) {
'<' -> {
if (currentChar == '=') {
pos.advance()
Token("<=", from, Token.Type.LTE)
if( currentChar == '>' ) {
pos.advance()
Token("<=>", from, Token.Type.SHUTTLE)
}
else {
Token("<=", from, Token.Type.LTE)
}
} else
Token("<", from, Token.Type.LT)
}

View File

@ -43,9 +43,75 @@ class Script(
(if (x is ObjInt) x
else ObjReal(round(x.toDouble())))
}
addFn("sin") {
ObjReal(sin(args.firstAndOnly().toDouble()))
}
addFn("cos") {
ObjReal(cos(args.firstAndOnly().toDouble()))
}
addFn("tan") {
ObjReal(tan(args.firstAndOnly().toDouble()))
}
addFn("asin") {
ObjReal(asin(args.firstAndOnly().toDouble()))
}
addFn("acos") {
ObjReal(acos(args.firstAndOnly().toDouble()))
}
addFn("atan") {
ObjReal(atan(args.firstAndOnly().toDouble()))
}
addFn("sinh") {
ObjReal(sinh(args.firstAndOnly().toDouble()))
}
addFn("cosh") {
ObjReal(cosh(args.firstAndOnly().toDouble()))
}
addFn("tanh") {
ObjReal(tanh(args.firstAndOnly().toDouble()))
}
addFn("asinh") {
ObjReal(asinh(args.firstAndOnly().toDouble()))
}
addFn("acosh") {
ObjReal(acosh(args.firstAndOnly().toDouble()))
}
addFn("atanh") {
ObjReal(atanh(args.firstAndOnly().toDouble()))
}
addFn("exp") {
ObjReal(exp(args.firstAndOnly().toDouble()))
}
addFn("ln") {
ObjReal(ln(args.firstAndOnly().toDouble()))
}
addFn("log10") {
ObjReal(log10(args.firstAndOnly().toDouble()))
}
addFn("log2") {
ObjReal(log2(args.firstAndOnly().toDouble()))
}
addFn("pow") {
requireExactCount(2)
ObjReal(
(args[0].toDouble()).pow(args[1].toDouble())
)
}
addFn("sqrt") {
ObjReal(
sqrt(args.firstAndOnly().toDouble())
)
}
addFn( "abs" ) {
val x = args.firstAndOnly()
if( x is ObjInt ) ObjInt( x.value.absoluteValue ) else ObjReal( x.toDouble().absoluteValue )
}
addVoidFn("assert") {
val cond = requiredArg<ObjBool>(0)

View File

@ -13,6 +13,7 @@ data class Token(val value: String, val pos: Pos, val type: Type) {
PLUS2, MINUS2,
IN, NOTIN, IS, NOTIS,
EQ, NEQ, LT, LTE, GT, GTE, REF_EQ, REF_NEQ,
SHUTTLE,
AND, BITAND, OR, BITOR, NOT, BITNOT, DOT, ARROW, QUESTION, COLONCOLON,
SINLGE_LINE_COMMENT, MULTILINE_COMMENT,
LABEL, ATLABEL, // label@ at@label

View File

@ -1192,6 +1192,52 @@ class ScriptTest {
fna(5,6)
"""
)
}
@Test
fun testSpoilLamdaArgsBug() = runTest {
eval(
"""
val fnb = { a,b -> a + b }
val fna = { a, b ->
val a0 = a
val b0 = b
fnb(a + 1, b + 1)
assert( a0 == a )
assert( b0 == b )
}
fna(5,6)
"""
)
}
@Test
fun commentBlocksShouldNotAlterBehavior() = runTest {
eval(
"""
fun test() {
10
/*
*/
//val x = 11
}
assert( test() == 10 )
""".trimIndent()
)
}
@Test
fun testShuttle() = runTest {
eval(
"""
assert( 5 <=> 3 > 0 )
assert( 0 < 5 <=> 3 )
assert( 5 <=> 5 == 0 )
assert( 5 <=> 7 < 0 )
""".trimIndent()
)
}
}

View File

@ -14,13 +14,12 @@ suspend fun executeSampleTests(fileName: String) {
}
runBlocking {
val c = Context()
for( i in 1..1) {
val start = Clock.System.now()
c.eval(sample)
val time = Clock.System.now() - start
println("$time: $fileName")
// delay(100)
}
// }
}
}