This commit is contained in:
nora 2022-07-04 08:38:14 +02:00
parent 1722a9ea0f
commit 1d56ed5dac
4 changed files with 26 additions and 28 deletions

View file

@ -14,49 +14,34 @@
[Interpreter] <--> () IO : stdin and stdout [Interpreter] <--> () IO : stdin and stdout
---- ----
Motivation::
The interpreter follows a classic interpreter architecture. First, the source is tokenized by a lexer, implemented using the `logos` library (https://crates.io/crates/logos). The interpreter follows a classic interpreter architecture. First, the source is tokenized by a lexer, implemented using the `logos` library (https://crates.io/crates/logos).
The, a handwritten recursive descent parser parses the token stream. The abstract syntax tree is then given to a small compiler, that compiles it down to a smaller and more limited IR. It also resolves jump labels to offsets. Then, a handwritten recursive descent parser parses the token stream. The abstract syntax tree is then given to a small compiler, that compiles it down to a smaller and more limited IR. It also resolves jump labels to offsets.
The interpreter then executes this lower level IR. The interpreter then executes this lower level IR.
==== Parser ==== Parser `parser.rs`
Lexes the source code, and then turns those tokens into an abstract syntax tree. Lexes the source code, and then parses those tokens into an abstract syntax tree.
[source,rust] [source,rust]
---- ----
include::{sourcedir}/parser.rs[tag=parse] include::{sourcedir}/parser.rs[tag=parse]
---- ----
_<(Optional) Quality/Performance Characteristics>_
_<(Optional) Directory/File Location>_ ==== Compiler and IR `ir.rs`
_<(Optional) Fulfilled Requirements>_ [source,rust]
----
include::{sourcedir}/ir.rs[tag=stmt]
----
_<(optional) Open Issues/Problems/Risks>_ The compiler compiles the AST into the IR, resolving labels.
==== Interpreter `interpret.rs`
The interpreter interprets the IR and interacts with the outside world through standard input and output.
==== <Name black box 2>
_<black box template>_
==== <Name black box n>
_<black box template>_
==== <Name interface 1>
...
==== <Name interface m>
=== Level 2 === Level 2

View file

@ -1,5 +1,18 @@
[[section-design-decisions]] [[section-design-decisions]]
== Architecture Decisions == Architecture Decisions
=== Use a single binary crate
Since the project is small and self-contained, using a single binary crate is enough. In the future, it could still be migrated to using a binary+library crate.
=== Use an IR
It would be simpler to simply walk over the AST during interpretation, but this presents several problems:
* The AST is more permissive than the language, therefore it would have to be checked at runtime.
* The AST is not optimized for interpretation efficiency, because it's not cache efficient.
* There would still have to be a second pass over the AST to resolve labels.
Therefore, an IR is used to resolve the labels and interpret it.

View file

@ -1,5 +1,3 @@
[[section-technical-risks]] [[section-technical-risks]]
== Risks and Technical Debts == Risks and Technical Debts

View file

@ -33,6 +33,7 @@ pub struct Location {
} }
#[derive(Debug, Clone, Copy, DebugPls)] #[derive(Debug, Clone, Copy, DebugPls)]
// tag::stmt[]
pub enum Stmt { pub enum Stmt {
Mov { to: Place, from: Value }, Mov { to: Place, from: Value },
Movb { to: Place, from: Value }, Movb { to: Place, from: Value },
@ -45,6 +46,7 @@ pub enum Stmt {
Je { to: Location }, Je { to: Location },
Cmp { lhs: Value, rhs: Value }, Cmp { lhs: Value, rhs: Value },
} }
// end::stmt[]
struct CompileCtx { struct CompileCtx {
stmts: Vec<Stmt>, stmts: Vec<Stmt>,