-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayground.ty
158 lines (135 loc) · 3.46 KB
/
playground.ty
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
pub type Motorcycle = struct {
name: [char],
wheels: u8
}
// Data has a type. can be manually declared with : <type>
const x = 7
const y: usize = 7
// Types have types
// this is usually redundant
type Car: struct {[char],u8} = struct {
name: [char],
wheels: u8
}
// you can achieve polymorphism and generics with traits
type Movable = trait {
set_wheels: fn(self, wheels: u8) void,
drive: fn(self) void
}
// you can then implement those traits
impl Car = trait(Movable) {
pub set_wheels = fn(self, wheels: u8) {
// do a thing!
}
}
// default implementations can be achieved
pub const set_wheels_default = fn(self: Movable, wheels: u8) void {
self.wheels = wheels
}
// default implementation
impl Motorcycle = trait(Movable) {
pub set_wheels = set_wheels_default
}
// macro/comptime
type Newable = trait {
new: fn(var: any[]) self {}
}
const add_new = macro(def: ident, var: any[]) {
impl def = trait(Newable) {
pub new = fn(expander(var)) {
return def {
dec_expand(var)
}
}
}
}
const expander = macro(name: ident, sig: signature, var: any[]) {
name: sig, expander(var)
}
const dec_expand = macro(name: ident, var: any[]) {
name: name, dec_expand(var)
}
add_new(Motorcycle, name, [char], wheels, u8)
// this expands to.
impl Motorcycle = trait(Newable) {
pub new = fn(name: [char], wheels: u8) {
return Motorcycle {
name: name,
wheels: wheels,
}
}
}
// these macro expressions are provided in the standard library
// to implement, simply declare your structs type
type MyThing = struct {
cool_string: [char]
}
// then call the compile time expansion macro
add_new(MyThing, cool_string, [char])
// comptime factorial
const factorial_table = comptime(name: ident, calculate: usize) {
const name = for (x in 0..calculate) {
return
}
}
const count_things = fn(to_check: &[char]) f64 {
let count: f64 = 0
for (to_check) fn(x) void {
if (x == ' ' || x == '7') {
count += 1
} else {
print('hello')
}
// possible match syntax
// forces exhaustion rather than if else chains missing a case
match (x) {
' ' || '7' => { count +=1 },
_ => { print('hello') },
}
match (x, y, z) {
'x', 'y', 'z' => { count +=1 },
_, 'y', 'z' => { print('hello') },
}
}
return count
}
type Kenobi = enum(u8) | Hello | There | General
// support line/block/fn
const thing = match (Kenobi.Hello) {
Kenobi.Hello => fn(m) usize {
return m as usize
},
Kenobi.There => { return 1 },
_ => return 2
// truthy values allow capturing.
// the truthy table is quite simple. if it has a value that is not empty or undefined. it is truthy.
const counter = fn() f64 {
let count: f64 = 0
let to_check = []
// to_check is an empty array. falsey
for (to_check) fn(x) void {
// unreachable!
}
if (to_check) fn(x) void {
// unreachable!
// because there is nothing in to_check, we can't capture the value. this makes truthy intuitive in type-lang
}
let my_str = ""
if (my_str) {
// unreachable!
// even when not capturing it follows the truthy rules, this block will never ran
}
let undef_example = undefined
if (undef_example) fn(x) void {
// unreachable!
// undefined is fine as a value, but we can never capture an undefined. undefined is never readable.
}
let actual = "captureable!"
for (actual) fn(x) void {
if (x.is_ascii()) {
}
}
}
const x: error!?usize = 7
const y: ?usize = try x
const z: usize = y?