~repos /plum
git clone https://pyrossh.dev/repos/plum.git
A statically typed, imperative programming language inspired by rust, python
0e69b5be
—
pyrossh 1 year ago
spec
- .eslintrc.json +8 -11
- example/aa.kk +0 -84
- example/fn.palm +5 -28
- example/std/bool.mi +10 -0
- example/std/buffer.mi +0 -0
- example/std/float.mi +97 -0
- example/std/int.mi +28 -0
- example/std/list.mi +35 -0
- example/std/map.mi +0 -0
- src/language/palm.langium +16 -14
.eslintrc.json
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
2
|
+
"root": true,
|
|
3
|
-
|
|
3
|
+
"parser": "@typescript-eslint/parser",
|
|
4
|
-
|
|
4
|
+
"parserOptions": {
|
|
5
|
-
|
|
5
|
+
"ecmaVersion": 6,
|
|
6
|
-
|
|
6
|
+
"sourceType": "module"
|
|
7
|
-
|
|
7
|
+
},
|
|
8
|
-
"plugins": [
|
|
9
|
-
|
|
8
|
+
"plugins": ["@typescript-eslint"],
|
|
10
|
-
],
|
|
11
|
-
|
|
9
|
+
"rules": {}
|
|
12
|
-
}
|
|
13
10
|
}
|
example/aa.kk
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
fun print10()
|
|
2
|
-
for(1,10) fn(i)
|
|
3
|
-
println(i)
|
|
4
|
-
|
|
5
|
-
fun encode2( s : string, shift : int )
|
|
6
|
-
s.map( fn(c)
|
|
7
|
-
if c < 'a' || c > 'z' then return c
|
|
8
|
-
val base = (c - 'a').int
|
|
9
|
-
val rot = (base + shift) % 26
|
|
10
|
-
(rot.char + 'a')
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
fun printhi10()
|
|
14
|
-
repeat(10)
|
|
15
|
-
println("hi")
|
|
16
|
-
|
|
17
|
-
fun sublist( xs : list<a>, start : int, len : int = xs.length ) : list<a>
|
|
18
|
-
if start <= 0 return xs.take(len)
|
|
19
|
-
match xs
|
|
20
|
-
Nil -> Nil
|
|
21
|
-
Cons(_,xx) -> xx.sublist(start - 1, len)
|
|
22
|
-
|
|
23
|
-
fun chisqr( xs : list<float64>, ys : list<float64> ) : float64
|
|
24
|
-
zipwith(xs,ys, fn(x,y) ((x - y)^2.0)/y ).foldr(0.0,(+))
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
fun fib(n : int) : div int
|
|
28
|
-
if n <= 0 then 0
|
|
29
|
-
elif n == 1 then 1
|
|
30
|
-
else fib(n - 1) + fib(n - 2)
|
|
31
|
-
|
|
32
|
-
fun fib2(n)
|
|
33
|
-
var x := 0
|
|
34
|
-
var y := 1
|
|
35
|
-
repeat(n)
|
|
36
|
-
val y0 = y
|
|
37
|
-
y := x+y
|
|
38
|
-
x := y0
|
|
39
|
-
x
|
|
40
|
-
|
|
41
|
-
fun wrong() : (() -> console ())
|
|
42
|
-
var x := 1
|
|
43
|
-
(fn(){ x := x + 1; println(x) })
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
struct person
|
|
47
|
-
age : int
|
|
48
|
-
name : string
|
|
49
|
-
realname : string = name
|
|
50
|
-
|
|
51
|
-
type person
|
|
52
|
-
Person
|
|
53
|
-
age : int
|
|
54
|
-
name : string
|
|
55
|
-
realname : string = name
|
|
56
|
-
|
|
57
|
-
val brian = Person( 29, "Brian" )
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
type color
|
|
61
|
-
Red
|
|
62
|
-
Green
|
|
63
|
-
Blue
|
|
64
|
-
|
|
65
|
-
type number
|
|
66
|
-
Infinity
|
|
67
|
-
Integer( i : int )
|
|
68
|
-
|
|
69
|
-
type bool
|
|
70
|
-
False
|
|
71
|
-
True
|
|
72
|
-
|
|
73
|
-
type list<a>
|
|
74
|
-
Nil
|
|
75
|
-
Cons{ head : a; tail : list<a> }
|
|
76
|
-
|
|
77
|
-
type tree
|
|
78
|
-
Tip
|
|
79
|
-
Bin( left: tree, value : int, right: tree )
|
|
80
|
-
|
|
81
|
-
fun tmap-inorder( t : tree, f : int -> int ) : tree
|
|
82
|
-
match t
|
|
83
|
-
Bin(l,x,r) -> Bin( l.tmap-inorder(f), f(x), r.tmap-inorder(f) )
|
|
84
|
-
Tip -> Tip
|
example/fn.palm
CHANGED
|
@@ -2,36 +2,13 @@ module lambda
|
|
|
2
2
|
|
|
3
3
|
alias MapCallback = fn(v: a): v
|
|
4
4
|
|
|
5
|
-
enum bool(true | false) =
|
|
6
|
-
fn op_eq(x: bool, y: bool) = x == y
|
|
7
|
-
fn op_ne(x: bool, y: bool) = x != y
|
|
8
|
-
fn op_and(x: bool, y: bool) = x && y
|
|
9
|
-
fn op_or(x: bool, y: bool) = x || y
|
|
10
|
-
fn op_xor(x: bool, y: bool) = x <> y
|
|
11
|
-
fn op_not(x: bool,): bool = !x
|
|
12
|
-
fn str(x: bool) = x ? "true" : "false"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
enum List<a>(First | Link(v: a, rest: List)) =
|
|
16
|
-
fn each(self, cb: fn(v: a)) =
|
|
17
|
-
match self
|
|
18
|
-
List::First -> List::First
|
|
19
|
-
List::link(v, rest) ->
|
|
20
|
-
cb(v)
|
|
21
|
-
each(rest, cb)
|
|
22
|
-
|
|
23
|
-
fn map(self, cb: fn(v: a): v) =
|
|
24
|
-
match self
|
|
25
|
-
First -> First
|
|
26
|
-
Link(v, rest) -> List::Link(cb(v), map(rest, cb))
|
|
27
|
-
|
|
28
|
-
enum Temperature(
|
|
5
|
+
enum Temperature(celsius(float) | fahrenheit(float)) =
|
|
29
6
|
fn str(self) =
|
|
30
7
|
match self
|
|
31
|
-
Temperature::
|
|
8
|
+
Temperature::celsius(t) && t > 30 -> "${t}C is above 30 celsius"
|
|
32
|
-
Temperature::
|
|
9
|
+
Temperature::celsius(t) -> "${t}C is below 30 celsius"
|
|
33
|
-
Temperature::
|
|
10
|
+
Temperature::fahrenheit(t) && t > 86 -> "${t}F is above 86 fahrenheit"
|
|
34
|
-
Temperature::
|
|
11
|
+
Temperature::fahrenheit(t) -> "${t}F is below 86 fahrenheit"
|
|
35
12
|
|
|
36
13
|
struct Cat(name: str, age: int) =
|
|
37
14
|
fn fullname() =
|
example/std/bool.mi
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module std
|
|
2
|
+
|
|
3
|
+
enum bool is (true | false) =
|
|
4
|
+
fn op_eq(x: bool, y: bool) = x == y
|
|
5
|
+
fn op_ne(x: bool, y: bool) = x != y
|
|
6
|
+
fn op_and(x: bool, y: bool) = x && y
|
|
7
|
+
fn op_or(x: bool, y: bool) = x || y
|
|
8
|
+
fn op_xor(x: bool, y: bool) = x <> y
|
|
9
|
+
fn op_not(x: bool,): bool = !x
|
|
10
|
+
fn str(x: bool) = x ? "true" : "false"
|
example/std/buffer.mi
ADDED
|
File without changes
|
example/std/float.mi
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
module std
|
|
2
|
+
|
|
3
|
+
primitive float =
|
|
4
|
+
E = 2.718f // Represents Euler's number, the base of natural logarithms, e
|
|
5
|
+
LN10 = 2.302f // Represents the natural logarithm of 10
|
|
6
|
+
LN2 = 0.693f // Represents the natural logarithm of 2
|
|
7
|
+
LOG10E = 0.434f // Represents the base 10 logarithm of e
|
|
8
|
+
LOG2E = 1.442f // Represents the base 2 logarithm of e
|
|
9
|
+
PI = 3.14159f // Represents the ratio of the circumference of a circle to its diameter
|
|
10
|
+
SQRT1_2 = 0.707f // Represents the square root of 1/2
|
|
11
|
+
SQRT2 = 1.414f // Represents the square root of 2
|
|
12
|
+
|
|
13
|
+
EPSILON = 2.220446049250313e-16f // Represents the difference between 1 and the smallest floating point number greater than 1
|
|
14
|
+
// MAX_SAFE_INTEGER
|
|
15
|
+
// MAX_VALUE
|
|
16
|
+
// MIN_SAFE_INTEGER
|
|
17
|
+
// MIN_VALUE
|
|
18
|
+
// NEGATIVE_INFINITY
|
|
19
|
+
// POSITIVE_INFINITY
|
|
20
|
+
|
|
21
|
+
// Returns the absolute value of a number
|
|
22
|
+
fn abs(v: float) = a < 0 ? -a : a
|
|
23
|
+
|
|
24
|
+
fn acos(v: float) = 0f
|
|
25
|
+
fn acosh(v: float) = 0f
|
|
26
|
+
fn asin(v: float) = 0f
|
|
27
|
+
fn asinh(v: float) = 0f
|
|
28
|
+
fn atan(v: float) = 0f
|
|
29
|
+
fn atan2(v: float) = 0f
|
|
30
|
+
fn atanh(v: float) = 0f
|
|
31
|
+
fn cbrt(v: float) = 0f
|
|
32
|
+
fn ceil(v: float) = 0f
|
|
33
|
+
fn clz32(v: float) = 0f
|
|
34
|
+
fn cos(v: float) = 0f
|
|
35
|
+
fn cosh(v: float) = 0f
|
|
36
|
+
fn exp(v: float) = 0f
|
|
37
|
+
fn to_int(): int = 0
|
|
38
|
+
fn to_str(): str = ""
|
|
39
|
+
|
|
40
|
+
fn random(): float =
|
|
41
|
+
0.0f
|
|
42
|
+
|
|
43
|
+
fn parse(s: str) =
|
|
44
|
+
0.0f
|
|
45
|
+
|
|
46
|
+
fn is_int(): bool = true
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
// Check whether this number is finite, ie not +/-infinity and not NaN.
|
|
50
|
+
fn is_finite(): bool = true
|
|
51
|
+
// True if exponent is not all 1s
|
|
52
|
+
// (bits() and 0x7FF0_0000_0000_0000) != 0x7FF0_0000_0000_0000
|
|
53
|
+
|
|
54
|
+
// Check whether this number is +/-infinity
|
|
55
|
+
fn is_infinite(): Bool =>
|
|
56
|
+
// True if exponent is all 1s and mantissa is 0
|
|
57
|
+
((bits() and 0x7FF0_0000_0000_0000) == 0x7FF0_0000_0000_0000) and // exp
|
|
58
|
+
((bits() and 0x000F_FFFF_FFFF_FFFF) == 0) // mantissa
|
|
59
|
+
|
|
60
|
+
// Check whether this number is NaN.
|
|
61
|
+
fn is_nan(): Bool =>
|
|
62
|
+
// True if exponent is all 1s and mantissa is non-0
|
|
63
|
+
((bits() and 0x7FF0_0000_0000_0000) == 0x7FF0_0000_0000_0000) and // exp
|
|
64
|
+
((bits() and 0x000F_FFFF_FFFF_FFFF) != 0) // mantissa
|
|
65
|
+
|
|
66
|
+
fn to_exponential(v: float): str = ""
|
|
67
|
+
|
|
68
|
+
fn to_fixed(v: float): str = ""
|
|
69
|
+
|
|
70
|
+
fn to_precision(v: float): str = ""
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
fn abs(): F64 = @"llvm.fabs.f64"(this)
|
|
74
|
+
fn ceil(): F64 = @"llvm.ceil.f64"(this)
|
|
75
|
+
fn floor(): F64 = @"llvm.floor.f64"(this)
|
|
76
|
+
fn round(): F64 = @"llvm.round.f64"(this)
|
|
77
|
+
fn trunc(): F64 = @"llvm.trunc.f64"(this)
|
|
78
|
+
|
|
79
|
+
fun log(): F64 => @"llvm.log.f64"(this)
|
|
80
|
+
fun log2(): F64 => @"llvm.log2.f64"(this)
|
|
81
|
+
fun log10(): F64 => @"llvm.log10.f64"(this)
|
|
82
|
+
fun logb(): F64 => @logb(this)
|
|
83
|
+
|
|
84
|
+
fun pow(y: F64): F64 => @"llvm.pow.f64"(this, y)
|
|
85
|
+
fun powi(y: I32): F64 =>
|
|
86
|
+
ifdef windows then
|
|
87
|
+
pow(y.f64())
|
|
88
|
+
else
|
|
89
|
+
@"llvm.powi.f64"(this, y)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
fun sqrt(): F64 =>
|
|
93
|
+
if this < 0.0 then
|
|
94
|
+
_nan()
|
|
95
|
+
else
|
|
96
|
+
@"llvm.sqrt.f64"(this)
|
|
97
|
+
end
|
example/std/int.mi
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module std
|
|
2
|
+
|
|
3
|
+
primitive int =
|
|
4
|
+
MIN_VALUE = 0
|
|
5
|
+
MAX_VALUE = 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF
|
|
6
|
+
|
|
7
|
+
fn random(): int =
|
|
8
|
+
0
|
|
9
|
+
|
|
10
|
+
fn min_value() => -0x8000_0000_0000_0000
|
|
11
|
+
fn max_value() => 0x7FFF_FFFF_FFFF_FFFF
|
|
12
|
+
fn abs(a: int): int => a < 0 ? -a : a
|
|
13
|
+
fn to_str(v: int): str = ""
|
|
14
|
+
|
|
15
|
+
fn op_add(x: int, y: int): int =
|
|
16
|
+
@"i64.add"(x, y)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
sub
|
|
20
|
+
mul
|
|
21
|
+
div
|
|
22
|
+
rem
|
|
23
|
+
|
|
24
|
+
min
|
|
25
|
+
max
|
|
26
|
+
|
|
27
|
+
to_float()
|
|
28
|
+
|
example/std/list.mi
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module std
|
|
2
|
+
|
|
3
|
+
enum List is (first | link(v: a, rest: List)) =
|
|
4
|
+
// where a : Number & Stringable
|
|
5
|
+
|
|
6
|
+
fn each(self, cb: fn(v: a)) =
|
|
7
|
+
match self
|
|
8
|
+
List::first -> List::first
|
|
9
|
+
List::link(v, rest) ->
|
|
10
|
+
cb(v)
|
|
11
|
+
each(rest, cb)
|
|
12
|
+
|
|
13
|
+
fn map(self, cb: fn(v: a): v) =
|
|
14
|
+
match self
|
|
15
|
+
List::first -> first
|
|
16
|
+
List::link(v, rest) -> List::link(cb(v), map(rest, cb))
|
|
17
|
+
|
|
18
|
+
fn get(i: int): a? =
|
|
19
|
+
match self
|
|
20
|
+
List::first -> List::first
|
|
21
|
+
List::link(v, rest) ->
|
|
22
|
+
each(rest, cb)
|
|
23
|
+
|
|
24
|
+
fun get<a>(lst :: List<a>, n :: Number) -> a:
|
|
25
|
+
doc: "Returns the nth element of the given list, or raises an error if n is out of range"
|
|
26
|
+
fun help(l, cur):
|
|
27
|
+
if is-empty(l): raise("get: n too large " + tostring(n))
|
|
28
|
+
else if cur == 0: l.first
|
|
29
|
+
else: help(l.rest, cur - 1)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
if n < 0: raise("get: invalid argument: " + tostring(n))
|
|
33
|
+
else: help(lst, n)
|
|
34
|
+
end
|
|
35
|
+
end
|
example/std/map.mi
ADDED
|
File without changes
|
src/language/palm.langium
CHANGED
|
@@ -7,7 +7,7 @@ Module:
|
|
|
7
7
|
'module' name=ID;
|
|
8
8
|
|
|
9
9
|
Type:
|
|
10
|
-
Primitive | Enum | Trait | Entity | Extension;
|
|
10
|
+
Primitive | Enum | Struct; //Trait | Entity | Extension;
|
|
11
11
|
|
|
12
12
|
Primitive:
|
|
13
13
|
'primitive' name=ID '{'
|
|
@@ -23,24 +23,24 @@ Enum:
|
|
|
23
23
|
EnumField:
|
|
24
24
|
name=ID ('(' (params+=Param (',' params+=Param)*)? ')')?;
|
|
25
25
|
|
|
26
|
-
Trait:
|
|
26
|
+
// Trait:
|
|
27
|
-
|
|
27
|
+
// 'trait' name=ID Generics '{'
|
|
28
|
-
|
|
28
|
+
// (methods+=FunctionDefinition<true, true>)*
|
|
29
|
-
|
|
29
|
+
// '}';
|
|
30
30
|
|
|
31
|
-
Extension:
|
|
31
|
+
// Extension:
|
|
32
|
-
|
|
32
|
+
// 'extension' name=ID 'on' type=[Entity] '{'
|
|
33
|
-
|
|
33
|
+
// (methods+=FunctionDefinition<true, false>)*
|
|
34
|
-
|
|
34
|
+
// '}';
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Struct:
|
|
37
|
-
'
|
|
37
|
+
'struct' name=ID Generics
|
|
38
38
|
(fields+=Field)*
|
|
39
39
|
(methods+=FunctionDefinition<true, false>)*
|
|
40
|
-
|
|
40
|
+
;
|
|
41
41
|
|
|
42
42
|
Field:
|
|
43
|
-
|
|
43
|
+
WS WS 'val' names+=ID ':' type=[Type:ID] NL;
|
|
44
44
|
|
|
45
45
|
fragment Generics:
|
|
46
46
|
('<' generics+=GENERIC_ID (',' generics+=GENERIC_ID)* '>')?;
|
|
@@ -103,7 +103,9 @@ terminal INT returns number: /[0-9]+/;
|
|
|
103
103
|
terminal STRING: /"(\\.|[^"\\])*"|'(\\.|[^'\\])*'/;
|
|
104
104
|
terminal HEX: /#(\d|[a-fA-F])+/;
|
|
105
105
|
terminal NUMBER returns number: /[0-9]+(\.[0-9]*)?[a-z]*/;
|
|
106
|
+
terminal WS: /\s/;
|
|
107
|
+
terminal NL: /\n/;
|
|
106
108
|
|
|
107
|
-
hidden terminal WS: /\s+/;
|
|
109
|
+
// hidden terminal WS: /\s+/;
|
|
108
110
|
hidden terminal ML_COMMENT: /\/\*[\s\S]*?\*\//;
|
|
109
111
|
hidden terminal SL_COMMENT: /\/\/[^\n\r]*/;
|