7250
This commit is contained in:
parent
264aba4d92
commit
8d2dece291
|
@ -13,7 +13,7 @@ fn main -> _/ebx: int {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do-add a: int, b: int -> _/eax: int {
|
fn do-add a: int, b: int -> _/eax: int {
|
||||||
var result/ebx: int <- copy a
|
var result/ecx: int <- copy a
|
||||||
result <- add b
|
result <- add b
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ if ('onhashchange' in window) {
|
||||||
<span id="L13" class="LineNr">13 </span><span class="Delimiter">}</span>
|
<span id="L13" class="LineNr">13 </span><span class="Delimiter">}</span>
|
||||||
<span id="L14" class="LineNr">14 </span>
|
<span id="L14" class="LineNr">14 </span>
|
||||||
<span id="L15" class="LineNr">15 </span><span class="PreProc">fn</span> <span class="muFunction"><a href='ex2.mu.html#L15'>do-add</a></span> a: int, b: int<span class="PreProc"> -> </span>_/<span class="Constant">eax</span>: int <span class="Delimiter">{</span>
|
<span id="L15" class="LineNr">15 </span><span class="PreProc">fn</span> <span class="muFunction"><a href='ex2.mu.html#L15'>do-add</a></span> a: int, b: int<span class="PreProc"> -> </span>_/<span class="Constant">eax</span>: int <span class="Delimiter">{</span>
|
||||||
<span id="L16" class="LineNr">16 </span> <span class="PreProc">var</span> result/<span class="Constant">ebx</span>: int <span class="SpecialChar"><-</span> copy a
|
<span id="L16" class="LineNr">16 </span> <span class="PreProc">var</span> result/<span class="Constant">ecx</span>: int <span class="SpecialChar"><-</span> copy a
|
||||||
<span id="L17" class="LineNr">17 </span> result <span class="SpecialChar"><-</span> add b
|
<span id="L17" class="LineNr">17 </span> result <span class="SpecialChar"><-</span> add b
|
||||||
<span id="L18" class="LineNr">18 </span> <span class="PreProc">return</span> result
|
<span id="L18" class="LineNr">18 </span> <span class="PreProc">return</span> result
|
||||||
<span id="L19" class="LineNr">19 </span><span class="Delimiter">}</span>
|
<span id="L19" class="LineNr">19 </span><span class="Delimiter">}</span>
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 98 KiB |
|
@ -59,9 +59,9 @@ if ('onhashchange' in window) {
|
||||||
<span id="L3" class="LineNr"> 3 </span><span class="subxComment"># See translate_mu for how this file is used.</span>
|
<span id="L3" class="LineNr"> 3 </span><span class="subxComment"># See translate_mu for how this file is used.</span>
|
||||||
<span id="L4" class="LineNr"> 4 </span><span class="subxComment">#</span>
|
<span id="L4" class="LineNr"> 4 </span><span class="subxComment">#</span>
|
||||||
<span id="L5" class="LineNr"> 5 </span><span class="subxComment"># Mu programs start at a function called 'main' with this signature:</span>
|
<span id="L5" class="LineNr"> 5 </span><span class="subxComment"># Mu programs start at a function called 'main' with this signature:</span>
|
||||||
<span id="L6" class="LineNr"> 6 </span><span class="subxComment"># fn main args: (addr array addr array byte) -> exit-status/ebx: int</span>
|
<span id="L6" class="LineNr"> 6 </span><span class="subxComment"># fn main args: (addr array addr array byte) -> _/ebx: int</span>
|
||||||
<span id="L7" class="LineNr"> 7 </span><span class="subxComment"># If your program doesn't need commandline arguments you can drop it:</span>
|
<span id="L7" class="LineNr"> 7 </span><span class="subxComment"># If your program doesn't need commandline arguments you can drop it:</span>
|
||||||
<span id="L8" class="LineNr"> 8 </span><span class="subxComment"># fn main -> exit-status/ebx: int</span>
|
<span id="L8" class="LineNr"> 8 </span><span class="subxComment"># fn main -> _/ebx: int</span>
|
||||||
<span id="L9" class="LineNr"> 9 </span><span class="subxComment">#</span>
|
<span id="L9" class="LineNr"> 9 </span><span class="subxComment">#</span>
|
||||||
<span id="L10" class="LineNr">10 </span><span class="subxComment"># Notice that the output must be in ebx, so that the exit() syscall can pick</span>
|
<span id="L10" class="LineNr">10 </span><span class="subxComment"># Notice that the output must be in ebx, so that the exit() syscall can pick</span>
|
||||||
<span id="L11" class="LineNr">11 </span><span class="subxComment"># it up.</span>
|
<span id="L11" class="LineNr">11 </span><span class="subxComment"># it up.</span>
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
# See translate_mu for how this file is used.
|
# See translate_mu for how this file is used.
|
||||||
#
|
#
|
||||||
# Mu programs start at a function called 'main' with this signature:
|
# Mu programs start at a function called 'main' with this signature:
|
||||||
# fn main args: (addr array addr array byte) -> exit-status/ebx: int
|
# fn main args: (addr array addr array byte) -> _/ebx: int
|
||||||
# If your program doesn't need commandline arguments you can drop it:
|
# If your program doesn't need commandline arguments you can drop it:
|
||||||
# fn main -> exit-status/ebx: int
|
# fn main -> _/ebx: int
|
||||||
#
|
#
|
||||||
# Notice that the output must be in ebx, so that the exit() syscall can pick
|
# Notice that the output must be in ebx, so that the exit() syscall can pick
|
||||||
# it up.
|
# it up.
|
||||||
|
|
30
mu.md
30
mu.md
|
@ -12,25 +12,17 @@ short, the former increments a value in memory, while the latter increments a
|
||||||
value in a register.
|
value in a register.
|
||||||
|
|
||||||
Most languages start from some syntax and do what it takes to implement it.
|
Most languages start from some syntax and do what it takes to implement it.
|
||||||
Mu, however, is designed as a safe[1] way to program in [a regular subset of
|
Mu, however, is designed as a safe way to program in [a regular subset of
|
||||||
32-bit x86 machine code](subx.md), _satisficing_ rather than optimizing for a
|
32-bit x86 machine code](subx.md), _satisficing_ rather than optimizing for a
|
||||||
clean syntax. To keep the mapping to machine code lightweight, Mu exclusively
|
clean syntax. To keep the mapping to machine code lightweight, Mu exclusively
|
||||||
uses statements. Most statements map to a single instruction of machine code.
|
uses statements. Most statements map to a single instruction of machine code.
|
||||||
|
|
||||||
[1] While it's designed to be memory-safe, and already performs many safety
|
|
||||||
checks, the Mu compiler is still a work in progress and can currently corrupt
|
|
||||||
memory just like C can. I estimate that it'll currently point out 90% of the
|
|
||||||
mistakes you make.
|
|
||||||
|
|
||||||
Since the x86 instruction set restricts how many memory locations an instruction
|
Since the x86 instruction set restricts how many memory locations an instruction
|
||||||
can use, Mu makes registers explicit as well. Variables must be explicitly
|
can use, Mu makes registers explicit as well. Variables must be explicitly
|
||||||
mapped to specific registers; otherwise they live in memory. While you have to
|
mapped to specific registers; otherwise they live in memory. While you have to
|
||||||
do your own register allocation, Mu will helpfully point out[2] when you get it
|
do your own register allocation, Mu will helpfully point out when you get it
|
||||||
wrong.
|
wrong.
|
||||||
|
|
||||||
[2] Again, there are some known issues here at the moment. I estimate that
|
|
||||||
it'll currently catch 95% of register allocation errors.
|
|
||||||
|
|
||||||
Statements consist of 3 parts: the operation, optional _inouts_ and optional
|
Statements consist of 3 parts: the operation, optional _inouts_ and optional
|
||||||
_outputs_. Outputs come before the operation name and `<-`.
|
_outputs_. Outputs come before the operation name and `<-`.
|
||||||
|
|
||||||
|
@ -67,9 +59,9 @@ fn _name_ _inout_ ... -> _output_ ... {
|
||||||
|
|
||||||
Each function has a header line, and some number of statements, each on a
|
Each function has a header line, and some number of statements, each on a
|
||||||
separate line. Headers describe inouts and outputs. Inouts can't be registers,
|
separate line. Headers describe inouts and outputs. Inouts can't be registers,
|
||||||
and outputs _must_ be registers. In the above example, the outputs of both
|
and outputs _must_ be registers. Outputs can't take names. In the above
|
||||||
`do-add` and `main` have type `int` and are available in register `ebx` at the
|
example, the outputs of both `do-add` and `main` have type `int` and are
|
||||||
end of the respective calls.
|
available in register `ebx` at the end of the respective calls.
|
||||||
|
|
||||||
The above program also demonstrates a function call (to the function `do-add`).
|
The above program also demonstrates a function call (to the function `do-add`).
|
||||||
Function calls look the same as primitive statements: they can return (multiple)
|
Function calls look the same as primitive statements: they can return (multiple)
|
||||||
|
@ -78,7 +70,7 @@ there's one more constraint: output registers must match the function header.
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```
|
```
|
||||||
fn f -> x/eax: int {
|
fn f -> _/eax: int {
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
fn g {
|
fn g {
|
||||||
|
@ -97,8 +89,8 @@ process). It can also optionally accept an array of strings as input (from the
|
||||||
shell command-line). To be precise, `main` must have one of the following
|
shell command-line). To be precise, `main` must have one of the following
|
||||||
two signatures:
|
two signatures:
|
||||||
|
|
||||||
- `fn main -> x/ebx: int`
|
- `fn main -> _/ebx: int`
|
||||||
- `fn main args: (addr array (addr array byte)) -> x/ebx: int`
|
- `fn main args: (addr array (addr array byte)) -> _/ebx: int`
|
||||||
|
|
||||||
(The names of the inout and output are flexible.)
|
(The names of the inout and output are flexible.)
|
||||||
|
|
||||||
|
@ -150,9 +142,9 @@ var name/reg: type <- ...
|
||||||
Variables on the stack are never initialized. (They're always implicitly
|
Variables on the stack are never initialized. (They're always implicitly
|
||||||
zeroed out.) Variables in registers are always initialized.
|
zeroed out.) Variables in registers are always initialized.
|
||||||
|
|
||||||
Register variables can go in 6 integer registers: `eax`, `ebx`, `ecx`, `edx`,
|
Register variables can go in 6 integer registers (`eax`, `ebx`, `ecx`, `edx`,
|
||||||
`esi` and `edi`. Floating-point values can go in 8 other registers: `xmm0`,
|
`esi`, `edi`) or 8 floating-point registers (`xmm0`, `xmm1`, `xmm2`, `xmm3`,
|
||||||
`xmm1`, `xmm2`, `xmm3`, `xmm4`, `xmm5`, `xmm6` and `xmm7`.
|
`xmm4`, `xmm5`, `xmm6`, `xmm7`).
|
||||||
|
|
||||||
Defining a variable in a register either clobbers the previous variable (if it
|
Defining a variable in a register either clobbers the previous variable (if it
|
||||||
was defined in the same block) or shadows it temporarily (if it was defined in
|
was defined in the same block) or shadows it temporarily (if it was defined in
|
||||||
|
|
Loading…
Reference in New Issue