-
Notifications
You must be signed in to change notification settings - Fork 0
/
operators.wil
178 lines (144 loc) · 3.8 KB
/
operators.wil
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
Here is the full list of operators in Wilfrid:
Mathematical:
+, -, *, /, %
Logical:
||, &&, !
Comparison:
==, !=, <, >, <=, >=
Bitwise:
|, &, ~, ^, <<, >>
Assignment:
=, +=, -=, *=, /=, %=, ||=, &&=, |=, &=, ^=, <<=, >>=
Pointer-related:
@, #, +, -
There are also increment (++) and decrement (--)
statements, working both for numbers and pointers.
Numeric types in Wilfrid are:
- int (signed 32-bit integer)
- uint (unsigned 32-bit integer)
- long (signed 64-bit integer)
- ulong (unsigned 64-bit integer)
- float (32-bit floating point number)
- char (unsigned 8-bit integer)
The rules of the implicit casting of numeric types are:
- a smaller type might be converted to a larger type
- an unsigned type might be converted to a signed type
- a non-float type might be converted to a float
- pointers and unsigned long integers can be converted both ways
- enum values and long integers can be converted both ways
In all other cases, explicit cast (using the 'as' keyword)
must be used. Some casts are not allowed, for example,
a cast from a numeric type to a struct.
*/
/*
Here are some example math functions making use of these
operators.
Calculating the n-th element of the Fibonacci series:
*/
fn get_fibonacci(n: int) : int
{
if (n == 0)
{
return 0
}
else if (n == 1)
{
return 1
}
else
{
return (get_fibonacci(n - 1) + get_fibonacci(n - 2))
}
}
fn fibonacci_example()
{
printf("First 10 elements of the Fibonacci series:\\n")
for (let i = 0, i < 10, i++)
{
printf("%d ", get_fibonacci(i))
}
printf("\\n")
}
/*
Calculating a Jenkins hash for a given byte sequence:
*/
fn jenkins_hash(key: char^, key_length: ulong) : uint
{
let hash : uint = 0
for (let i : ulong = 0, i < key_length, i++)
{
hash += #(key + i)
hash += hash << 10
hash ^= hash >> 6
}
hash += hash << 3
hash ^= hash >> 11
hash += hash << 15
return hash
}
fn jenkins_hash_example()
{
let key = "Synoptic vision"
let hash = jenkins_hash(key, get_string_length(key))
printf("The Jenkins hash for the string '%s':\\n%u\\n", key, hash)
}
/*
Setting flags on a 64-bit field via bitwise operators:
*/
enum flags
{
FLAG_A = 1,
FLAG_B = 2,
FLAG_C = 4
}
fn set_flags_example()
{
let some_flags =
(flags.FLAG_A as ulong | flags.FLAG_B as ulong | flags.FLAG_C as ulong)
let is_flag_a_set := (some_flags & flags.FLAG_A)
let is_flag_b_set := (some_flags & flags.FLAG_B)
let is_flag_c_set := (some_flags & flags.FLAG_C)
if (is_flag_a_set && is_flag_b_set && is_flag_c_set)
{
printf("All three flags are set\\n")
}
}
/*
Calculating a rectangle intersection:
*/
fn are_intersecting(a: rectangle, b: rectangle) : bool
{
let x_axis_intersect :=
!(b.max_corner.x <= a.min_corner.x
|| b.min_corner.x >= a.max_corner.x)
let y_axis_intersect :=
!(b.max_corner.y <= a.min_corner.y
|| b.min_corner.y >= a.max_corner.y)
return (x_axis_intersect && y_axis_intersect)
}
fn intersection_example()
{
let a : rectangle = { { 1.5, 1.0 }, { 4.0, 3.2 } }
let b : rectangle = { { 0.0, 0.5 }, { 3.0, 1.1 } }
let intersection = are_intersecting(a, b)
printf("Are rectangles intersecting? %s\\n",
intersection ? "Yes" : "No")
}
struct vector2
{
x: float,
y: float
}
struct rectangle
{
min_corner: vector2,
max_corner: vector2
}
fn main()
{
fibonacci_example()
jenkins_hash_example()
set_flags_example()
intersection_example()
}