fixed runtime stack missalignment

This commit is contained in:
Sven Vogel 2023-01-02 12:56:53 +01:00
parent 1b62b0fc4e
commit 981a6688d4
6 changed files with 129 additions and 89 deletions

View File

@ -1,35 +1,63 @@
## Yard
Yard is an funny programming language compiler and interpreter written in pure Rust.
Its a functional language, having no concept of classes or inheritance. Types are static and must be known at compile time.
It contains features such as:
Its a functional language, having no concept of classes or inheritance. Types are static and must be known at compile time.
1. a COMEFROM keyword (inverse goto)
2. a `don't` code block which never executes
3. no if. only `unless`, an inverted version of if. Meaning a block gets executed if the expression is false
4. three spaces start a single line comment
5. many ways of making comments: `// comment`, `:REM: comment`, `# comment`, `-- comment --` cuz we can
### Primitve data types 
The language has 4 primitive data types:
* `bool` a 1 byte boolean value which is either true or false. It can also be initalised with a random value at compile time iwht `maybe`
* `int` a 8 byte two's complement signed integer with 64-bit of storage space
* `rat` a 8 byte IEEE-754 double precision floating point value
* `str` a dynamically sized immutable string wich for now can only be used with the concatonation operator `..`
NOTE: no custom data types such as structs or classes are supported.
### Keywords
<table><tbody><tr><td>Syntax</td><td>Description</td><td>Example</td></tr><tr><td>Unless</td><td>Inverted if. Only executes the following block if the expression is false</td><td><pre><code class="language-plaintext">unless 3 &gt; 4 {
<table><tbody><tr><td>Syntax</td><td>Description</td><td>Example</td></tr><tr><td>despite</td><td>Inverted if. Only executes the following block if the expression is false</td><td><pre><code class="language-plaintext">despite 3 &gt; 4 {
// code block
}</code></pre></td></tr><tr><td>Loop</td><td>While(true)-Loop. Loops forever until either yield, ret, break are used.<br>Loop take no boolean expression.</td><td><pre><code class="language-plaintext">loop {
}</code></pre></td></tr><tr><td>loop</td><td>While(true)-Loop. Loops forever until either yield, ret, break are used.<br>Loop take no boolean expression.</td><td><pre><code class="language-plaintext">loop {
// code block
}</code></pre></td></tr><tr><td>cont</td><td>Short form for “continue”. Jumps to the next iteration of a loop</td><td>&nbsp;</td></tr><tr><td>break</td><td>Exits a loop immediately</td><td>&nbsp;</td></tr><tr><td>yield</td><td>Returns from a function with an argument as return value</td><td><pre><code class="language-plaintext">foo() = int {
}</code></pre></td></tr><tr><td>cont</td><td>Short form for “continue”. Jumps to the next iteration of a loop</td><td><pre><code class="language-plaintext">loop {
cont;
}</code></pre></td></tr><tr><td>break</td><td>Exits a loop immediately</td><td><pre><code class="language-plaintext">loop {
break;
}</code></pre></td></tr><tr><td>yield</td><td>Returns from a function with an argument as return value</td><td><pre><code class="language-plaintext">foo() = int {
yield 4
}</code></pre></td></tr><tr><td>ret</td><td>Short form for “return”. This keyword takes no argument and returns from a function. NOTE: if ret is used in a function with a return type, an error occurs.</td><td>&nbsp;</td></tr><tr><td>please</td><td>Decides on runtime wether a block should be executed or not.</td><td><pre><code class="language-plaintext">please {
// code
}</code></pre></td></tr></tbody></table>
}</code></pre></td></tr><tr><td>ret</td><td>Short form for “return”. This keyword takes no argument and returns from a function. NOTE: if ret is used in a function with a return type, an error occurs.</td><td><pre><code class="language-plaintext">foo() {
ret // exit function
}</code></pre></td></tr><tr><td>please</td><td>Decides on runtime wether a block should be executed or not.</td><td><pre><code class="language-plaintext">please {
// code
}</code></pre></td></tr><tr><td>unless</td><td>Works like a while loop except inverted. it will only run if the condition is false.</td><td><pre><code class="language-plaintext">unless x &gt; 5 {
// code
}</code></pre></td></tr><tr><td>goto</td><td>jumps to a specified label</td><td><pre><code class="language-plaintext">'label
// code
goto label;</code></pre></td></tr></tbody></table>
### Example code
```plaintext
foo(bar: int, abc:int) = int {
bar + abc
-- compute the factorial
-- in a recursive and functional way
fac(x:int) = int {
despite x != 1 {
yield 1;
}
yield fac(x - 1) * x
}
main {
foo(4, 5)
number = rat 34 # this is a function without arguments and a braceless body
// main function
main = int {
result = fac(number);
println("The Factorial of " .. number .. " is: " .. result);
yield 0;
}
```

View File

@ -1,39 +1,46 @@
section[text]
0xa2b0391a480300b:
push float 12
extern builtin 0x80b0eba54530cdc3
extern builtin 0xcd262c6e6c32473d
0xc8c7a99bb88e156b:
push int 0x0
call 0xa2b0391a480300b
call 0x80b0eba54530cdc3
call 0x967b65e0e8f1394
store 0x0
load 0x0
push int 0x9
cmp gt int
jump-unless 0x19
load 0x0
push int 0x5
cmp not-eq int
jump-unless 0xf
load 0x0
push int 0x1
add int
store 0x0
jump 0x2
push string ""
push string "The Factorial of "
call 0xa2b0391a480300b
push string " is: "
load 0x0
cat
call 0xa451e518c3d4dbea
call 0x396ceaf58c7ab783
load 0x0
cat
cat
call 0xe2e27e92bf406d33
push int 0x0
store 0x1
load 0x1
push int 0x9
cmp gt int
jump-unless 0x1b
push string ""
load 0x1
cat
call 0xe2e27e92bf406d33
load 0x1
push int 0x1
add int
store 0x0
jump 0x2
jump 0x1b
jump 0x2
store 0x1
jump 0xe
push int 0x0
ret
extern builtin 0x396ceaf58c7ab783
extern builtin 0xe2e27e92bf406d33
extern builtin 0x608aa48c89877fc5
extern builtin 0x8207427514e5a880
0x967b65e0e8f1394:
load 0x0
@ -50,8 +57,8 @@ extern builtin 0x608aa48c89877fc5
mul int
ret
extern builtin 0xdcd0c37eed9c3ddf
extern builtin 0x3e6a3810b5f0c581
extern builtin 0x6d3c1164316ec324
extern builtin 0x443bc4709cf7af32
extern builtin 0xa451e518c3d4dbea
extern builtin 0x23a9f04bf6903826

View File

@ -596,7 +596,7 @@ const TOKEN_REGEX_SRC: &'static str = concat!(
r"|'([a-zA-Z0-9_]+)", // labels: 'example
r"|(goto\s+[a-zA-Z0-9_]+", // goto example
r"|despite|until|loop|break|cont|ret|yield|please)", // keywords
r"|\W(int|rat|bool|str)\W", // raw data types
r"|[\W\s]{0,1}(int|rat|bool|str)[\W\s]{0,1}", // raw data types
r"|(true|false|ye|no|maybe)", // boolean values
r"|([A-Za-z_]+)\s*(?::\s*([a-zA-Z0-9_]+))?\s*=[^=]", // assignment var:int=
r"|([A-Za-z_]+)\s*(?::\s*([a-zA-Z0-9_]+))", // declaration var:int

View File

@ -368,9 +368,10 @@ fn parse_term<'a>(
if decl.name.as_ref().unwrap() == name {
code.push(Instr::Call(decl.uuid()));
ct.stacksize -= decl.args.as_ref().unwrap_or(&Vec::new()).len();
if decl.results {
ct.stacksize += 1;
ct.stacksize -= decl.args.as_ref().unwrap_or(&Vec::new()).len();
}
}
}

View File

@ -4,9 +4,13 @@ extern function print
extern function println
extern function print
extern function to_rat
extern function println
extern function to_int
extern function parse_int
extern function parse_rat
fac:
Load Arg x
@ -23,33 +27,37 @@ fac:
Mul Int
Yield
number:
Load Rat 12.0
main:
Call number
Call to_int
Call fac
Store Int result
Load String "The Factorial of "
Call number
Load String " is: "
Load Var result
Cat Str
Cat Str
Cat Str
Call println
Load Int 0
Store Int x
Loop
Loopstart
Loopstart
Load Var x
Load Int 9
Gt Int
While
Load String ""
Load Var x
Load Int 9
Gt Int
While
Load Var x
Load Int 5
NotEq Int
Unless
Load Var x
Load Int 1
Add Int
Store Int x
Continue
Load String ""
Load Var x
Cat Str
Call println
Load Var x
Load Int 1
Add Int
Store Int x
Break
Cat Str
Call println
Load Var x
Load Int 1
Add Int
Store Int x
Load Int 0
Yield

View File

@ -1,8 +1,9 @@
@feature(io)
@feature(io, conv)
@version(100)
@author(Sven Vogel)
// recursion!
-- compute the factorial
-- in a recursive and functional way
fac(x:int) = int {
despite x != 1 {
yield 1;
@ -11,25 +12,20 @@ fac(x:int) = int {
yield fac(x - 1) * x
}
main() = int {
x = 0
loop {
number = rat 12.0 # this is a function without arguments and a braceless body
until x > 9 {
despite x != 5 {
x = x + 1
cont
}
// main function
main = int {
println(""..x);
x = x + 1
}
result = fac(to_int(number));
break
println("The Factorial of " .. number() .. " is: " .. result);
x:int = 0;
until x > 9 {
println("" .. x);
x = x + 1
}
println(""..fract(456.3928));
yield 0
yield 0;
}