I am trying to emulate section 3 of Parsing a simple imperative language (Haskell). In particular, I am considering a stack based language instead of an imperative language, and I am trying to right idiomatic Rust code to represent the data.
Suppose you want to make a small (really small) stack based language that has some basic arithmetic operations, no user defined functions, and works on decimal numbers and integers. So for example:
1 2 +
-> Stack contains: 3
What's going on? Read from left to right, push 1 and 2 on the stack, and the +
would push off the 1
and 2
and then push 3
(= 1 + 2
) onto the stack.
My idea is there to consider 3
types of "primitives" that need parsing. You have integers, decimal numbers, and functions. Furthermore, decimal and integers numbers are both "nouns", and functions are "verbs". So when executing a program my idea was you could represent these ideas in Rust by extending the idea of the Result<T, E>
enum. I came up with the following scheme:
enum Noun {
Integer(i64),
Decimal(f64)
}
enum Primitive<T> {
Noun(T),
Verb(Fn(Vec<Noun>) -> Noun),
}
// Not really important, just giving a main so it can be ran
fn main() {
println!("Hello, world!");
}
In other words, a primitive is either a Noun
or a Verb
, and Noun
is either an integer or a float.
However, this results in:
error[E0277]: the trait bound `std::ops::Fn(std::vec::Vec<Noun>) -> Noun + 'static: std::marker::Sized` is not satisfied
--> main.rs:8:10
|
8 | Verb(Fn(Vec<Noun>) -> Noun),
| ^^^^^^^^^^^^^^^^^^^^^^ `std::ops::Fn(std::vec::Vec<Noun>) -> Noun + 'static` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `std::ops::Fn(std::vec::Vec<Noun>) -> Noun + 'static`
= note: only the last field of a struct may have a dynamically sized type
error: aborting due to previous error(s)
What would be the standard way of doing this in Rust?