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
Yard is an funny programming language compiler and interpreter written in pure Rust. 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. 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:
1. a COMEFROM keyword (inverse goto) ### Primitve data types 
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 The language has 4 primitive data types:
4. three spaces start a single line comment
5. many ways of making comments: `// comment`, `:REM: comment`, `# comment`, `-- comment --` cuz we can * `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 ### 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 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 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 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></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() {
// code ret // exit function
}</code></pre></td></tr></tbody></table> }</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 ### Example code
```plaintext ```plaintext
foo(bar: int, abc:int) = int { -- compute the factorial
bar + abc -- in a recursive and functional way
fac(x:int) = int {
despite x != 1 {
yield 1;
}
yield fac(x - 1) * x
} }
main { number = rat 34 # this is a function without arguments and a braceless body
foo(4, 5)
// main function
main = int {
result = fac(number);
println("The Factorial of " .. number .. " is: " .. result);
yield 0;
} }
``` ```

View File

@ -1,39 +1,46 @@
section[text] section[text]
0xa2b0391a480300b:
push float 12
extern builtin 0x80b0eba54530cdc3
extern builtin 0xcd262c6e6c32473d
0xc8c7a99bb88e156b: 0xc8c7a99bb88e156b:
push int 0x0 call 0xa2b0391a480300b
call 0x80b0eba54530cdc3
call 0x967b65e0e8f1394
store 0x0 store 0x0
load 0x0 push string "The Factorial of "
push int 0x9 call 0xa2b0391a480300b
cmp gt int push string " is: "
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 ""
load 0x0 load 0x0
cat cat
call 0xa451e518c3d4dbea cat
call 0x396ceaf58c7ab783 cat
load 0x0 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 push int 0x1
add int add int
store 0x0 store 0x1
jump 0x2 jump 0xe
jump 0x1b
jump 0x2
push int 0x0 push int 0x0
ret ret
extern builtin 0x396ceaf58c7ab783 extern builtin 0xe2e27e92bf406d33
extern builtin 0x608aa48c89877fc5 extern builtin 0x8207427514e5a880
0x967b65e0e8f1394: 0x967b65e0e8f1394:
load 0x0 load 0x0
@ -50,8 +57,8 @@ extern builtin 0x608aa48c89877fc5
mul int mul int
ret 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"|'([a-zA-Z0-9_]+)", // labels: 'example
r"|(goto\s+[a-zA-Z0-9_]+", // goto example r"|(goto\s+[a-zA-Z0-9_]+", // goto example
r"|despite|until|loop|break|cont|ret|yield|please)", // keywords 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"|(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_]+))?\s*=[^=]", // assignment var:int=
r"|([A-Za-z_]+)\s*(?::\s*([a-zA-Z0-9_]+))", // declaration 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 { if decl.name.as_ref().unwrap() == name {
code.push(Instr::Call(decl.uuid())); code.push(Instr::Call(decl.uuid()));
ct.stacksize -= decl.args.as_ref().unwrap_or(&Vec::new()).len();
if decl.results { if decl.results {
ct.stacksize += 1; 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 println
extern function print extern function to_rat
extern function println extern function to_int
extern function parse_int
extern function parse_rat
fac: fac:
Load Arg x Load Arg x
@ -23,33 +27,37 @@ fac:
Mul Int Mul Int
Yield Yield
number:
Load Rat 12.0
main: 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 Load Int 0
Store Int x Store Int x
Loop Loopstart
Loopstart Load Var x
Load Int 9
Gt Int
While
Load String ""
Load Var x Load Var x
Load Int 9 Cat Str
Gt Int Call println
While Load Var x
Load Var x Load Int 1
Load Int 5 Add Int
NotEq Int Store Int x
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
Load Int 0 Load Int 0
Yield Yield

View File

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