diff --git a/CHANGELOG.md b/CHANGELOG.md index 210f9e5a..045bfb13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -185,4 +185,67 @@ println(main()); The compiler is significantly faster -- about 20 times faster at compiling the AES example. This is mainly due to the much faster parser implemented with Nom instead of Pest. There are also several optimizations with constant evaluation I added, along with optimizations -for how declarations are typechecked. \ No newline at end of file +for how declarations are typechecked. + + +## [0.1.1-alpha] - 2024-9-8 + +### Added + +Added `const` generics, so constant parameters can be passed along with types through templates. This allows the typechecker to be applied to many more aspects of code, including examples like typechecking dimensions of matrix multiplications at compile time. + +```rs +struct Matrix { + arr: [[T * Cols] * Rows] +} + +impl Matrix { + fun new(x: T): Matrix { + return {arr=[[x] * Cols] * Rows}; + } + + fun get(&self, row: Int, col: Int): &T { + return &self.arr[row][col]; + } + + fun mul( + &self, + other: &Matrix, + zero: T, + add: fun(T, T) -> T, + mul: fun(T, T) -> T + ): Matrix { + let mut result = Matrix.new(zero); + for let mut j=0; j(10); +let mut y = Matrix.new(5); + +println(x); +println(y); + +fun add_ints(a: Int, b: Int): Int = a + b; +fun mul_ints(a: Int, b: Int): Int = a * b; + +let z = y.mul<4>(&x, 0, add_ints, mul_ints); +println(z); +``` + +### Changed + +Changed type system to accommodate const generics. This was done by adding a `ConstParam` variant to types. + +### Fixed + +Improved parser speed by a significant amount during the process. \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 765c5812..0b735db4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ rayon = "1.10" ## ERROR REPORTING ####################################### codespan-reporting = "0.11" -log = {version = "0.4", features = ["release_max_level_error"] } +log = {version = "0.4", features = ["release_max_level_info"] } env_logger = "0.11" ####################################### @@ -87,5 +87,5 @@ harness = false [dev-dependencies] criterion = "0.5" -[profile.release] -debug = true +# [profile.release] +# debug = true diff --git a/README.md b/README.md index 307b4f38..13214454 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,7 @@ Go to the [web-demo](https://adam-mcdaniel.net/sage) or the [examples/frontend]( - [ ] VSCode extension (syntax highlighting, code completion, etc.) - [ ] Typeclasses - [ ] `no-std` implementation of compiler +- [x] `const` generics - [x] Modules - [x] A standard library - [ ] Type Reflection Module diff --git a/docs/sage/asm/core/struct.CoreProgram.html b/docs/sage/asm/core/struct.CoreProgram.html index df8e8398..94bdba4d 100644 --- a/docs/sage/asm/core/struct.CoreProgram.html +++ b/docs/sage/asm/core/struct.CoreProgram.html @@ -21,9 +21,9 @@ The message is a message to be logged before the instructions. This tells some context about the instructions being logged. The i is the instruction number to start logging at. -This will log all instructions until the end of the program.
source§

impl Clone for CoreProgram

source§

fn clone(&self) -> CoreProgram

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for CoreProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for CoreProgram

A default program is an empty program.

+This will log all instructions until the end of the program.
source§

impl Clone for CoreProgram

source§

fn clone(&self) -> CoreProgram

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for CoreProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for CoreProgram

A default program is an empty program.

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl<'de> Deserialize<'de> for CoreProgram

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for CoreProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<CoreProgram> for StandardProgram

source§

fn from(core: CoreProgram) -> Self

Converts to this type from the input type.
source§

impl Hash for CoreProgram

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for CoreProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<CoreProgram> for StandardProgram

source§

fn from(core: CoreProgram) -> Self

Converts to this type from the input type.
source§

impl Hash for CoreProgram

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for CoreProgram

source§

fn cmp(&self, other: &CoreProgram) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/asm/enum.Error.html b/docs/sage/asm/enum.Error.html index 1889a510..62ff6b3c 100644 --- a/docs/sage/asm/enum.Error.html +++ b/docs/sage/asm/enum.Error.html @@ -14,8 +14,8 @@
§

Unmatched(CoreOp, usize)

The given instruction did not have a matching “end”. This is used for If, Else, While, For, and Fn statements.

§

Unexpected(CoreOp, usize)

The given instruction was not expected, or cannot be used in this context.

-

Trait Implementations§

source§

impl Clone for Error

source§

fn clone(&self) -> Error

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl From<Error> for Error

Create an IR error from an assembly error.

-
source§

fn from(e: Error) -> Self

Converts to this type from the input type.
source§

impl From<Error> for Error

source§

fn from(e: Error) -> Self

Converts to this type from the input type.
source§

impl PartialEq for Error

source§

fn eq(&self, other: &Error) -> bool

This method tests for self and other values to be equal, and is used +

Trait Implementations§

source§

impl Clone for Error

source§

fn clone(&self) -> Error

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl From<Error> for Error

source§

fn from(e: Error) -> Self

Converts to this type from the input type.
source§

impl From<Error> for Error

Create an IR error from an assembly error.

+
source§

fn from(e: Error) -> Self

Converts to this type from the input type.
source§

impl PartialEq for Error

source§

fn eq(&self, other: &Error) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for Error

source§

fn partial_cmp(&self, other: &Error) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= diff --git a/docs/sage/asm/std/enum.StandardOp.html b/docs/sage/asm/std/enum.StandardOp.html index ef174310..303ccd74 100644 --- a/docs/sage/asm/std/enum.StandardOp.html +++ b/docs/sage/asm/std/enum.StandardOp.html @@ -186,8 +186,8 @@
§

VecACos

Fields

§size: usize

Perform a SIMD floating point inverse cosine operation.

§

VecATan

Fields

§size: usize

Perform a SIMD floating point inverse tangent operation.

§

VecGez

Fields

§size: usize

Perform a SIMD floating point greater than or equal to zero operation.

-

Trait Implementations§

source§

impl Clone for StandardOp

source§

fn clone(&self) -> StandardOp

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for StandardOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for StandardOp

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for StandardOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for StandardOp

source§

fn eq(&self, other: &StandardOp) -> bool

This method tests for self and other values to be equal, and is used +

Trait Implementations§

source§

impl Clone for StandardOp

source§

fn clone(&self) -> StandardOp

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for StandardOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for StandardOp

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for StandardOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for StandardOp

source§

fn eq(&self, other: &StandardOp) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for StandardOp

source§

fn partial_cmp(&self, other: &StandardOp) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= diff --git a/docs/sage/asm/std/struct.StandardProgram.html b/docs/sage/asm/std/struct.StandardProgram.html index 69e7b96d..b503f5de 100644 --- a/docs/sage/asm/std/struct.StandardProgram.html +++ b/docs/sage/asm/std/struct.StandardProgram.html @@ -24,9 +24,9 @@ The message is a message to be logged before the instructions. This tells some context about the instructions being logged. The i is the instruction number to start logging at. -This will log all instructions until the end of the program.
source§

impl Clone for StandardProgram

source§

fn clone(&self) -> StandardProgram

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for StandardProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for StandardProgram

A default program is an empty program.

+This will log all instructions until the end of the program.
source§

impl Clone for StandardProgram

source§

fn clone(&self) -> StandardProgram

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for StandardProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for StandardProgram

A default program is an empty program.

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl<'de> Deserialize<'de> for StandardProgram

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for StandardProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<CoreProgram> for StandardProgram

source§

fn from(core: CoreProgram) -> Self

Converts to this type from the input type.
source§

impl PartialEq for StandardProgram

source§

fn eq(&self, other: &StandardProgram) -> bool

This method tests for self and other values to be equal, and is used + __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for StandardProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<CoreProgram> for StandardProgram

source§

fn from(core: CoreProgram) -> Self

Converts to this type from the input type.
source§

impl PartialEq for StandardProgram

source§

fn eq(&self, other: &StandardProgram) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for StandardProgram

source§

fn partial_cmp(&self, other: &StandardProgram) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= diff --git a/docs/sage/lir/enum.Arithmetic.html b/docs/sage/lir/enum.Arithmetic.html index c0179d70..65678728 100644 --- a/docs/sage/lir/enum.Arithmetic.html +++ b/docs/sage/lir/enum.Arithmetic.html @@ -7,33 +7,34 @@ Remainder, Power, }
Expand description

An arithmetic operation.

-

Variants§

§

Add

§

Subtract

§

Multiply

§

Divide

§

Remainder

§

Power

Trait Implementations§

source§

impl BinaryOp for Arithmetic

source§

fn can_apply(&self, lhs: &Type, rhs: &Type, env: &Env) -> Result<bool, Error>

Can this binary operation be applied to the given types?

-
source§

fn return_type(&self, lhs: &Expr, rhs: &Expr, env: &Env) -> Result<Type, Error>

Get the type of the result of applying this binary operation to the given types.

-
source§

fn eval( +

Variants§

§

Add

§

Subtract

§

Multiply

§

Divide

§

Remainder

§

Power

Trait Implementations§

source§

impl BinaryOp for Arithmetic

source§

fn compile( + &self, + lhs: &Expr, + rhs: &Expr, + env: &mut Env, + output: &mut dyn AssemblyProgram +) -> Result<(), Error>

Compiles the operation on the given expressions.

+
source§

fn can_apply(&self, lhs: &Type, rhs: &Type, env: &Env) -> Result<bool, Error>

Can this binary operation be applied to the given types?

+
source§

fn return_type(&self, lhs: &Expr, rhs: &Expr, env: &Env) -> Result<Type, Error>

Get the type of the result of applying this binary operation to the given types.

+
source§

fn eval( &self, lhs: &ConstExpr, rhs: &ConstExpr, env: &mut Env ) -> Result<ConstExpr, Error>

Evaluate this binary operation on the given constant values.

-
source§

fn compile_types( +

source§

fn compile_types( &self, - lhs: &Type, - rhs: &Type, - env: &mut Env, - output: &mut dyn AssemblyProgram + _lhs: &Type, + _rhs: &Type, + _env: &mut Env, + _output: &mut dyn AssemblyProgram ) -> Result<(), Error>

Compile the binary operation.

-
source§

fn clone_box(&self) -> Box<dyn BinaryOp>

Clones the operation into a boxed trait object.
source§

fn name(&self) -> String

source§

fn type_check(&self, lhs: &Expr, rhs: &Expr, env: &Env) -> Result<(), Error>

Typechecks the operation on the given expressions.
source§

fn display(&self, lhs: &Expr, rhs: &Expr) -> String

Formats the operation for display.
source§

fn can_apply_exprs( +

source§

fn clone_box(&self) -> Box<dyn BinaryOp>

Clones the operation into a boxed trait object.
source§

fn name(&self) -> String

source§

fn type_check(&self, lhs: &Expr, rhs: &Expr, env: &Env) -> Result<(), Error>

Typechecks the operation on the given expressions.
source§

fn display(&self, lhs: &Expr, rhs: &Expr) -> String

Formats the operation for display.
source§

fn can_apply_exprs( &self, lhs: &Expr, rhs: &Expr, env: &Env -) -> Result<bool, Error>

Checks if the operation can be applied to the given expressions.
source§

fn compile( - &self, - lhs: &Expr, - rhs: &Expr, - env: &mut Env, - output: &mut dyn AssemblyProgram -) -> Result<(), Error>

Compiles the operation on the given expressions.
source§

impl Clone for Arithmetic

source§

fn clone(&self) -> Arithmetic

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Arithmetic

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Arithmetic

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Copy for Arithmetic

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where +) -> Result<bool, Error>

Checks if the operation can be applied to the given expressions.
source§

impl Clone for Arithmetic

source§

fn clone(&self) -> Arithmetic

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Arithmetic

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Arithmetic

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Copy for Arithmetic

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/docs/sage/lir/enum.ConstExpr.html b/docs/sage/lir/enum.ConstExpr.html index a8fffecb..6b7a9753 100644 --- a/docs/sage/lir/enum.ConstExpr.html +++ b/docs/sage/lir/enum.ConstExpr.html @@ -1,7 +1,8 @@ -ConstExpr in sage::lir - Rust -

Enum sage::lir::ConstExpr

source ·
pub enum ConstExpr {
-
Show 29 variants Annotated(Box<Self>, Annotation), +ConstExpr in sage::lir - Rust +

Enum sage::lir::ConstExpr

source ·
pub enum ConstExpr {
+
Show 30 variants Annotated(Box<Self>, Annotation), Declare(Box<Declaration>, Box<Self>), + Any, None, Null, Symbol(String), @@ -26,11 +27,12 @@ Proc(Procedure), PolyProc(PolyProcedure), Monomorphize(Box<Self>, Vec<Type>), - Template(Vec<String>, Box<Self>), + Template(Vec<(String, Option<Type>)>, Box<Self>), Member(Box<Self>, Box<Self>), As(Box<Self>, Type),
}
Expand description

A compiletime expression.

Variants§

§

Annotated(Box<Self>, Annotation)

§

Declare(Box<Declaration>, Box<Self>)

Bind a list of types in a constant expression.

+
§

Any

The expression equal to any other expression.

§

None

The unit, or “void” instance.

§

Null

The null pointer constant.

§

Symbol(String)

A named constant.

@@ -58,50 +60,50 @@
§

Proc(Procedure)

A procedure.

§

PolyProc(PolyProcedure)

A polymorphic procedure.

§

Monomorphize(Box<Self>, Vec<Type>)

Monomorphize a constant expression with some type arguments.

-
§

Template(Vec<String>, Box<Self>)

§

Member(Box<Self>, Box<Self>)

Get an attribute of a constant expression.

+
§

Template(Vec<(String, Option<Type>)>, Box<Self>)

§

Member(Box<Self>, Box<Self>)

Get an attribute of a constant expression.

§

As(Box<Self>, Type)

Cast a constant expression to another type.

-

Implementations§

source§

impl ConstExpr

source

pub fn monomorphize(self, ty_args: Vec<Type>) -> Self

source

pub fn template(&self, params: Vec<String>) -> Self

source

pub fn var(var: impl ToString) -> Self

Evaluate a variable in the current scope.

-
source

pub fn proc( +

Implementations§

source§

impl ConstExpr

source

pub fn monomorphize(self, ty_args: Vec<Type>) -> Self

source

pub fn equals(&self, other: &Self, env: &Env) -> bool

source

pub fn template(&self, params: Vec<(String, Option<Type>)>) -> Self

source

pub fn var(var: impl ToString) -> Self

Evaluate a variable in the current scope.

+
source

pub fn proc( common_name: Option<String>, args: Vec<(String, Mutability, Type)>, ret: Type, body: impl Into<Expr> ) -> Self

Construct a procedure.

-
source

pub fn with(&self, older_decls: impl Into<Declaration>) -> Self

Return this expression, but with a given declaration in scope.

-
source

pub fn annotate(self, annotation: Annotation) -> Self

Annotate this constant expression with a source code location.

-
source

pub fn app(self, args: Vec<Expr>) -> Expr

Apply this procedure or builtin to a list of expressions at runtime.

-
source

pub fn eval(self, env: &Env) -> Result<Self, Error>

Evaluate this constant expression at compile time, +

source

pub fn with(&self, older_decls: impl Into<Declaration>) -> Self

Return this expression, but with a given declaration in scope.

+
source

pub fn annotate(self, annotation: Annotation) -> Self

Annotate this constant expression with a source code location.

+
source

pub fn app(self, args: Vec<Expr>) -> Expr

Apply this procedure or builtin to a list of expressions at runtime.

+
source

pub fn eval(self, env: &Env) -> Result<Self, Error>

Evaluate this constant expression at compile time, and get the result.

-
source

pub fn as_type(self, t: Type) -> Self

Cast an expression as another type.

-
source

pub fn field(self, field: ConstExpr) -> Self

Get a field from a structure, union, or tuple.

+
source

pub fn as_type(self, t: Type) -> Self

Cast an expression as another type.

+
source

pub fn field(self, field: ConstExpr) -> Self

Get a field from a structure, union, or tuple.

For tuples, use an Int constant expression to access the nth field (zero indexed). For unions or structures, use a Symbol constant expression to access the field.

-
source

pub fn as_int(self, env: &Env) -> Result<i64, Error>

Try to get this constant expression as an integer.

-
source

pub fn as_char(self, env: &Env) -> Result<char, Error>

Try to get this constant expression as a character.

-
source

pub fn as_float(self, env: &Env) -> Result<f64, Error>

Try to get this constant expression as a float.

-
source

pub fn as_bool(self, env: &Env) -> Result<bool, Error>

Try to get this constant expression as a boolean value.

-
source

pub fn as_symbol(self, env: &Env) -> Result<String, Error>

Try to get this constant expression as a symbol (like in LISP).

-

Trait Implementations§

source§

impl Clone for ConstExpr

source§

fn clone(&self) -> ConstExpr

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Compile for ConstExpr

Compile a constant expression.

-
source

pub fn as_int(self, env: &Env) -> Result<i64, Error>

Try to get this constant expression as an integer.

+
source

pub fn as_char(self, env: &Env) -> Result<char, Error>

Try to get this constant expression as a character.

+
source

pub fn as_float(self, env: &Env) -> Result<f64, Error>

Try to get this constant expression as a float.

+
source

pub fn as_bool(self, env: &Env) -> Result<bool, Error>

Try to get this constant expression as a boolean value.

+
source

pub fn as_symbol(self, env: &Env) -> Result<String, Error>

Try to get this constant expression as a symbol (like in LISP).

+

Trait Implementations§

source§

impl Clone for ConstExpr

source§

fn clone(&self) -> ConstExpr

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Compile for ConstExpr

Compile a constant expression.

+
source§

fn compile_expr( self, env: &mut Env, output: &mut dyn AssemblyProgram ) -> Result<(), Error>

source§

fn compile(self) -> Result<Result<CoreProgram, StandardProgram>, Error>
where - Self: Sized + Clone,

Compile the expression into an assembly program. Read more
source§

impl Debug for ConstExpr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for ConstExpr

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for ConstExpr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<ConstExpr> for Expr

source§

fn from(c: ConstExpr) -> Self

Converts to this type from the input type.
source§

impl GetType for ConstExpr

source§

fn get_type_checked(&self, env: &Env, i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check -recursion depth to prevent a possible stack overflow.
source§

fn substitute(&mut self, name: &str, subsitution: &Type)

Substitute a type for a given name in the environment.
source§

fn get_type(&self, env: &Env) -> Result<Type, Error>

Get the type associated with a value under a given environment.
source§

fn substitute_types(&mut self, names: &[String], types: &[Type])

source§

impl Hash for ConstExpr

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where + Self: Sized + Clone,

Compile the expression into an assembly program. Read more
source§

impl Debug for ConstExpr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for ConstExpr

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for ConstExpr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<ConstExpr> for Expr

source§

fn from(c: ConstExpr) -> Self

Converts to this type from the input type.
source§

impl From<PolyProcedure> for ConstExpr

source§

fn from(value: PolyProcedure) -> Self

Converts to this type from the input type.
source§

impl From<Procedure> for ConstExpr

source§

fn from(value: Procedure) -> Self

Converts to this type from the input type.
source§

impl From<Type> for ConstExpr

source§

fn from(value: Type) -> Self

Converts to this type from the input type.
source§

impl GetType for ConstExpr

source§

fn get_type_checked(&self, env: &Env, i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check +recursion depth to prevent a possible stack overflow.
source§

fn substitute(&mut self, name: &str, substitution: &Type)

Substitute a type for a given name in the environment.
source§

fn get_type(&self, env: &Env) -> Result<Type, Error>

Get the type associated with a value under a given environment.
source§

fn substitute_types(&mut self, names: &[String], types: &[Type])

source§

impl Hash for ConstExpr

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl PartialEq for ConstExpr

source§

fn eq(&self, other: &ConstExpr) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Serialize for ConstExpr

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where - __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl Simplify for ConstExpr

source§

fn simplify_checked(self, env: &Env, i: usize) -> Result<Self, Error>

Simplify an expression while maintaining structural equality, but limit + __S: Serializer,
Serialize this value into the given Serde serializer. Read more
source§

impl Simplify for ConstExpr

source§

fn simplify_checked(self, env: &Env, i: usize) -> Result<Self, Error>

Simplify an expression while maintaining structural equality, but limit the number of recursive calls to prevent stack overflow. i is a -counter to prevent infinite recursion.
source§

fn simplify(self, env: &Env) -> Result<Self, Error>

Simplify an expression while maintaining structural equality.
source§

impl TypeCheck for ConstExpr

source§

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.
source§

impl Eq for ConstExpr

source§

impl Send for ConstExpr

source§

impl StructuralPartialEq for ConstExpr

source§

impl Sync for ConstExpr

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where +counter to prevent infinite recursion.

source§

fn simplify(self, env: &Env) -> Result<Self, Error>

Simplify an expression while maintaining structural equality.
source§

impl TypeCheck for ConstExpr

source§

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.
source§

impl Eq for ConstExpr

source§

impl Send for ConstExpr

source§

impl StructuralPartialEq for ConstExpr

source§

impl Sync for ConstExpr

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where - T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

-
source§

impl<T> GetSize for T
where - T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive + T: ?Sized,
source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T> GetSize for T
where + T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive calls to prevent stack overflow. i is a counter to prevent infinite recursion.
source§

fn get_size(&self, env: &Env) -> Result<usize, Error>

Get the size of something in memory (number of cells).
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

diff --git a/docs/sage/lir/enum.Declaration.html b/docs/sage/lir/enum.Declaration.html index b697fff6..3613cf45 100644 --- a/docs/sage/lir/enum.Declaration.html +++ b/docs/sage/lir/enum.Declaration.html @@ -35,21 +35,21 @@
§

FromImport

Fields

§module: ConstExpr

Import an element from a module.

§

FromImportAll(ConstExpr)

Implementations§

source§

impl Declaration

source

pub fn many(decls: impl Into<Vec<Self>>) -> Self

Create a collection of declarations

source

pub fn module(name: impl ToString, decls: impl Into<Vec<Self>>) -> Self

Create a module with a given name and a list of declarations

-

Trait Implementations§

source§

impl<T> Add<T> for Declaration
where - T: Into<Declaration>,

§

type Output = Declaration

The resulting type after applying the + operator.
source§

fn add(self, other: T) -> Self::Output

Performs the + operation. Read more
source§

impl<T> AddAssign<T> for Declaration
where - T: Into<Declaration>,

source§

fn add_assign(&mut self, other: T)

Performs the += operation. Read more
source§

impl Clone for Declaration

source§

fn clone(&self) -> Declaration

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Declaration

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Declaration

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Declaration

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl From<(&str, ConstExpr)> for Declaration

source§

fn from((name, proc): (&str, ConstExpr)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Expr)> for Declaration

source§

fn from((name, expr): (&str, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, FFIProcedure)> for Declaration

source§

fn from((name, proc): (&str, FFIProcedure)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Mutability, Expr)> for Declaration

source§

fn from((name, mutability, expr): (&str, Mutability, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Mutability, Option<Type>, Expr)> for Declaration

Trait Implementations§

source§

impl<T> Add<T> for Declaration
where + T: Into<Declaration>,

§

type Output = Declaration

The resulting type after applying the + operator.
source§

fn add(self, other: T) -> Self::Output

Performs the + operation. Read more
source§

impl<T> AddAssign<T> for Declaration
where + T: Into<Declaration>,

source§

fn add_assign(&mut self, other: T)

Performs the += operation. Read more
source§

impl Clone for Declaration

source§

fn clone(&self) -> Declaration

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Declaration

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Declaration

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Declaration

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl From<(&str, ConstExpr)> for Declaration

source§

fn from((name, proc): (&str, ConstExpr)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Expr)> for Declaration

source§

fn from((name, expr): (&str, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, FFIProcedure)> for Declaration

source§

fn from((name, proc): (&str, FFIProcedure)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Mutability, Expr)> for Declaration

source§

fn from((name, mutability, expr): (&str, Mutability, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Mutability, Option<Type>, Expr)> for Declaration

source§

fn from( (name, mutability, ty, expr): (&str, Mutability, Option<Type>, Expr) -) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Mutability, Type, Expr)> for Declaration

source§

fn from((name, mutability, ty, expr): (&str, Mutability, Type, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, PolyProcedure)> for Declaration

source§

fn from((name, proc): (&str, PolyProcedure)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Procedure)> for Declaration

source§

fn from((name, proc): (&str, Procedure)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Type)> for Declaration

source§

fn from((name, expr): (&str, Type)) -> Self

Converts to this type from the input type.
source§

impl From<(Pattern, Expr)> for Declaration

source§

fn from((pat, expr): (Pattern, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(String, ConstExpr)> for Declaration

source§

fn from((name, expr): (String, ConstExpr)) -> Self

Converts to this type from the input type.
source§

impl From<(String, Expr)> for Declaration

source§

fn from((name, expr): (String, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(String, FFIProcedure)> for Declaration

source§

fn from((name, proc): (String, FFIProcedure)) -> Self

Converts to this type from the input type.
source§

impl From<(String, Mutability, Expr)> for Declaration

source§

fn from((name, mutability, expr): (String, Mutability, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(String, Mutability, Option<Type>, Expr)> for Declaration

source§

fn from( +) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Mutability, Type, Expr)> for Declaration

source§

fn from((name, mutability, ty, expr): (&str, Mutability, Type, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, PolyProcedure)> for Declaration

source§

fn from((name, proc): (&str, PolyProcedure)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Procedure)> for Declaration

source§

fn from((name, proc): (&str, Procedure)) -> Self

Converts to this type from the input type.
source§

impl From<(&str, Type)> for Declaration

source§

fn from((name, expr): (&str, Type)) -> Self

Converts to this type from the input type.
source§

impl From<(Pattern, Expr)> for Declaration

source§

fn from((pat, expr): (Pattern, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(String, ConstExpr)> for Declaration

source§

fn from((name, expr): (String, ConstExpr)) -> Self

Converts to this type from the input type.
source§

impl From<(String, Expr)> for Declaration

source§

fn from((name, expr): (String, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(String, FFIProcedure)> for Declaration

source§

fn from((name, proc): (String, FFIProcedure)) -> Self

Converts to this type from the input type.
source§

impl From<(String, Mutability, Expr)> for Declaration

source§

fn from((name, mutability, expr): (String, Mutability, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(String, Mutability, Option<Type>, Expr)> for Declaration

source§

fn from( (name, mutability, ty, expr): (String, Mutability, Option<Type>, Expr) -) -> Self

Converts to this type from the input type.
source§

impl From<(String, Mutability, Type, Expr)> for Declaration

source§

fn from((name, mutability, ty, expr): (String, Mutability, Type, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(String, PolyProcedure)> for Declaration

source§

fn from((name, proc): (String, PolyProcedure)) -> Self

Converts to this type from the input type.
source§

impl From<(String, Procedure)> for Declaration

source§

fn from((name, proc): (String, Procedure)) -> Self

Converts to this type from the input type.
source§

impl From<(String, Type)> for Declaration

source§

fn from((name, ty): (String, Type)) -> Self

Converts to this type from the input type.
source§

impl<K, V> From<BTreeMap<K, V>> for Declaration

source§

fn from(bt: BTreeMap<K, V>) -> Self

Converts to this type from the input type.
source§

impl From<Box<Declaration>> for Declaration

source§

fn from(x: Box<Self>) -> Self

Converts to this type from the input type.
source§

impl<T> From<Vec<T>> for Declaration
where - T: Into<Declaration>,

source§

fn from(decls: Vec<T>) -> Self

Converts to this type from the input type.
source§

impl Hash for Declaration

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +) -> Self

Converts to this type from the input type.
source§

impl From<(String, Mutability, Type, Expr)> for Declaration

source§

fn from((name, mutability, ty, expr): (String, Mutability, Type, Expr)) -> Self

Converts to this type from the input type.
source§

impl From<(String, PolyProcedure)> for Declaration

source§

fn from((name, proc): (String, PolyProcedure)) -> Self

Converts to this type from the input type.
source§

impl From<(String, Procedure)> for Declaration

source§

fn from((name, proc): (String, Procedure)) -> Self

Converts to this type from the input type.
source§

impl From<(String, Type)> for Declaration

source§

fn from((name, ty): (String, Type)) -> Self

Converts to this type from the input type.
source§

impl<K, V> From<BTreeMap<K, V>> for Declaration

source§

fn from(bt: BTreeMap<K, V>) -> Self

Converts to this type from the input type.
source§

impl From<Box<Declaration>> for Declaration

source§

fn from(x: Box<Self>) -> Self

Converts to this type from the input type.
source§

impl<T> From<Vec<T>> for Declaration
where + T: Into<Declaration>,

source§

fn from(decls: Vec<T>) -> Self

Converts to this type from the input type.
source§

impl Hash for Declaration

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl PartialEq for Declaration

source§

fn eq(&self, other: &Declaration) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Serialize for Declaration

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where - __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl TypeCheck for Declaration

source§

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.
source§

impl StructuralPartialEq for Declaration

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl TypeCheck for Declaration

source§

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.
source§

impl StructuralPartialEq for Declaration

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/docs/sage/lir/enum.Error.html b/docs/sage/lir/enum.Error.html index 04f46787..729145ce 100644 --- a/docs/sage/lir/enum.Error.html +++ b/docs/sage/lir/enum.Error.html @@ -1,7 +1,11 @@ -Error in sage::lir - Rust -
§1: Annotation

The location of the source code that caused the error. This is used for error reporting.

An error with some annotation about the source code that caused the error.

-
§

UnimplementedOperator(String)

§

AssemblyError(Error)

An error caused by trying to assemble invalid code generated by the compiler. +

§

UnimplementedOperator(String)

§

UnexpectedConstParam

Fields

§found: Type
§expr: Expr

An error caused by unexpectedly passing a constant parameter to a template.

+
§

AssemblyError(Error)

An error caused by trying to assemble invalid code generated by the compiler. This should be taken seriously, unless the error is due to an invalid handwritten builtin.

§

VariantNotFound(Type, String)

The variant of an enum is not defined.

§

MemberNotFound(Expr, ConstExpr)

Tried to access an undefined member of a tuple, struct, or union.

@@ -102,9 +107,9 @@
§

CompilePolyProc(PolyProcedure)

Tried to compile a polymorphic procedure without monomorphing it.

§

InvalidMonomorphize(ConstExpr)

Cannot monomorphize a constant expression.

§

DuplicateMember(Type, String)

Duplicate implementations of a member for a type

-

Implementations§

source§

impl Error

source

pub fn annotate(self, annotation: Annotation) -> Self

Annotate an error with some metadata.

-

Trait Implementations§

source§

impl Clone for Error

source§

fn clone(&self) -> Error

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl From<Error> for Error

Create an IR error from an assembly error.

-
source§

fn from(e: Error) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl !RefUnwindSafe for Error

§

impl Send for Error

§

impl Sync for Error

§

impl Unpin for Error

§

impl !UnwindSafe for Error

Blanket Implementations§

source§

impl<T> Any for T
where +

Implementations§

source§

impl Error

source

pub fn annotate(self, annotation: Annotation) -> Self

Annotate an error with some metadata.

+

Trait Implementations§

source§

impl Clone for Error

source§

fn clone(&self) -> Error

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl From<Error> for Error

Create an IR error from an assembly error.

+
source§

fn from(e: Error) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl !RefUnwindSafe for Error

§

impl Send for Error

§

impl Sync for Error

§

impl Unpin for Error

§

impl !UnwindSafe for Error

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/docs/sage/lir/enum.Expr.html b/docs/sage/lir/enum.Expr.html index 99b13f4e..755a228c 100644 --- a/docs/sage/lir/enum.Expr.html +++ b/docs/sage/lir/enum.Expr.html @@ -76,44 +76,44 @@ For unions or structures, use a Symbol constant expression to access the field.

Do NOT instantiate this directly: use the .field method on the container expression.

§

Index(Box<Self>, Box<Self>)

Index an array or pointer with an expression that evaluates to an Int at runtime.

-

Implementations§

source§

impl Expr

source

pub const NONE: Self = _

A constant expression that evaluates to None. +

Implementations§

source§

impl Expr

source

pub const NONE: Self = _

A constant expression that evaluates to None. This constant is defined so that we don’t have to write Expr::ConstExpr every time we want to use None.

-
source

pub fn print(self) -> Self

source

pub fn println(self) -> Self

source

pub fn is_method_call(&self, env: &Env) -> Result<bool, Error>

source

pub fn transform_method_call(&self, env: &Env) -> Result<Self, Error>

source

pub fn get_method_call_mutability( +

source

pub fn print(self) -> Self

source

pub fn println(self) -> Self

source

pub fn is_method_call(&self, env: &Env) -> Result<bool, Error>

source

pub fn transform_method_call(&self, env: &Env) -> Result<Self, Error>

source

pub fn get_method_call_mutability( &self, env: &Env -) -> Result<Option<Mutability>, Error>

source

pub fn annotate(&self, annotation: impl Into<Annotation>) -> Self

An annotated expression with some metadata.

-
source

pub fn with(&self, older_decls: impl Into<Declaration>) -> Self

Return this expression, but with a given declaration in scope.

-
source

pub fn hard_with(&self, older_decls: impl Into<Declaration>) -> Self

source

pub fn size_of(self) -> Self

Get the size of an expression.

-
source

pub fn as_type(self, t: Type) -> Self

Cast an expression as another type.

-
source

pub fn unop(self, op: impl ToString) -> Self

Apply a unary operation to this expression.

-
source

pub fn not(self) -> Self

Logical not this expression.

-
source

pub fn bitxor(self, other: impl Into<Self>) -> Self

Bitwise this expression with another.

-
source

pub fn bitor(self, other: impl Into<Self>) -> Self

BitwiseOr this expression with another.

-
source

pub fn bitnand(self, other: impl Into<Self>) -> Self

BitwiseOr this expression with another.

-
source

pub fn bitand(self, other: impl Into<Self>) -> Self

BitwiseAnd this expression with another.

-
source

pub fn bitnor(self, other: impl Into<Self>) -> Self

BitwiseAnd this expression with another.

-
source

pub fn bitnot(self) -> Self

BitwiseAnd this expression with another.

-
source

pub fn lt(self, other: impl Into<Self>) -> Self

Is this expression less than another?

-
source

pub fn le(self, other: impl Into<Self>) -> Self

Is this expression less than or equal to another?

-
source

pub fn gt(self, other: impl Into<Self>) -> Self

Is this expression greater than another?

-
source

pub fn ge(self, other: impl Into<Self>) -> Self

Is this expression greater than or equal to another?

-
source

pub fn eq(self, other: impl Into<Self>) -> Self

Is this expression greater than another?

-
source

pub fn neq(self, other: impl Into<Self>) -> Self

Is this expression greater than or equal to another?

-
source

pub fn and(self, other: impl Into<Self>) -> Self

Logical and this expression with another.

-
source

pub fn or(self, other: impl Into<Self>) -> Self

Logical or this expression with another.

-
source

pub fn pow(self, exp: impl Into<Self>) -> Self

Get the power of this expression to another.

-
source

pub fn add(self, other: impl Into<Self>) -> Self

Add this expression to another.

-
source

pub fn sub(self, other: impl Into<Self>) -> Self

Subtract an expression from this expression.

-
source

pub fn mul(self, other: impl Into<Self>) -> Self

Multiply this expression by another.

-
source

pub fn div(self, other: impl Into<Self>) -> Self

Divide this expression by another.

-
source

pub fn rem(self, other: impl Into<Self>) -> Self

Get the remainder of this expression divided by another.

-
source

pub fn neg(self) -> Self

Get the remainder of this expression divided by another.

-
source

pub fn field(self, field: ConstExpr) -> Self

Get a field from a structure, union, or tuple.

+) -> Result<Option<Mutability>, Error>
source

pub fn annotate(&self, annotation: impl Into<Annotation>) -> Self

An annotated expression with some metadata.

+
source

pub fn with(&self, older_decls: impl Into<Declaration>) -> Self

Return this expression, but with a given declaration in scope.

+
source

pub fn hard_with(&self, older_decls: impl Into<Declaration>) -> Self

source

pub fn size_of(self) -> Self

Get the size of an expression.

+
source

pub fn as_type(self, t: Type) -> Self

Cast an expression as another type.

+
source

pub fn unop(self, op: impl ToString) -> Self

Apply a unary operation to this expression.

+
source

pub fn not(self) -> Self

Logical not this expression.

+
source

pub fn bitxor(self, other: impl Into<Self>) -> Self

Bitwise this expression with another.

+
source

pub fn bitor(self, other: impl Into<Self>) -> Self

BitwiseOr this expression with another.

+
source

pub fn bitnand(self, other: impl Into<Self>) -> Self

BitwiseOr this expression with another.

+
source

pub fn bitand(self, other: impl Into<Self>) -> Self

BitwiseAnd this expression with another.

+
source

pub fn bitnor(self, other: impl Into<Self>) -> Self

BitwiseAnd this expression with another.

+
source

pub fn bitnot(self) -> Self

BitwiseAnd this expression with another.

+
source

pub fn lt(self, other: impl Into<Self>) -> Self

Is this expression less than another?

+
source

pub fn le(self, other: impl Into<Self>) -> Self

Is this expression less than or equal to another?

+
source

pub fn gt(self, other: impl Into<Self>) -> Self

Is this expression greater than another?

+
source

pub fn ge(self, other: impl Into<Self>) -> Self

Is this expression greater than or equal to another?

+
source

pub fn eq(self, other: impl Into<Self>) -> Self

Is this expression greater than another?

+
source

pub fn neq(self, other: impl Into<Self>) -> Self

Is this expression greater than or equal to another?

+
source

pub fn and(self, other: impl Into<Self>) -> Self

Logical and this expression with another.

+
source

pub fn or(self, other: impl Into<Self>) -> Self

Logical or this expression with another.

+
source

pub fn pow(self, exp: impl Into<Self>) -> Self

Get the power of this expression to another.

+
source

pub fn add(self, other: impl Into<Self>) -> Self

Add this expression to another.

+
source

pub fn sub(self, other: impl Into<Self>) -> Self

Subtract an expression from this expression.

+
source

pub fn mul(self, other: impl Into<Self>) -> Self

Multiply this expression by another.

+
source

pub fn div(self, other: impl Into<Self>) -> Self

Divide this expression by another.

+
source

pub fn rem(self, other: impl Into<Self>) -> Self

Get the remainder of this expression divided by another.

+
source

pub fn neg(self) -> Self

Get the remainder of this expression divided by another.

+
source

pub fn field(self, field: ConstExpr) -> Self

Get a field from a structure, union, or tuple.

For tuples, use an Int constant expression to access the nth field (zero indexed). For unions or structures, use a Symbol constant expression to access the field.

-
source

pub fn idx(self, idx: impl Into<Self>) -> Self

Index an array or pointer with an expression that evaluates to an Int at runtime.

-
source

pub fn let_var( +

source

pub fn idx(self, idx: impl Into<Self>) -> Self

Index an array or pointer with an expression that evaluates to an Int at runtime.

+
source

pub fn let_var( var: impl ToString, mutability: impl Into<Mutability>, t: Option<Type>, @@ -124,17 +124,17 @@ var will be declared with the type t, and the expression e will be assigned to it.

The result of this expression is the ret value, which is evaluated under this new scope.

When this expression is finished evaluating, var will be removed from the scope.

-

source

pub fn let_vars( +

source

pub fn let_vars( vars: Vec<(&str, Mutability, Option<Type>, Self)>, ret: impl Into<Self> ) -> Self

Create a let binding for an expression, and define multiple variables.

-
source

pub fn let_type(typename: impl ToString, t: Type, ret: impl Into<Self>) -> Self

Create a let binding for an type.

+
source

pub fn let_type(typename: impl ToString, t: Type, ret: impl Into<Self>) -> Self

Create a let binding for an type.

This will create a new scope with the type typename defined. typename will be declared with the type t, and the expression ret will be evaluated under this new scope.

When this expression is finished evaluating, typename will be removed from the scope.

-
source

pub fn let_types(vars: Vec<(&str, Type)>, ret: impl Into<Self>) -> Self

Create several type bindings at onces.

-
source

pub fn let_const( +

source

pub fn let_types(vars: Vec<(&str, Type)>, ret: impl Into<Self>) -> Self

Create several type bindings at onces.

+
source

pub fn let_const( constname: impl ToString, e: ConstExpr, ret: impl Into<Self> @@ -142,11 +142,11 @@

This will create a new scope with the constant constname defined. ret will be evaluated under this new scope.

When this expression is finished evaluating, constname will be removed from the scope.

-

source

pub fn let_consts( +

source

pub fn let_consts( constants: Vec<(&str, ConstExpr)>, ret: impl Into<Self> ) -> Self

Create several const bindings at onces.

-
source

pub fn let_proc( +

source

pub fn let_proc( procname: impl ToString, proc: Procedure, ret: impl Into<Self> @@ -154,18 +154,18 @@

This will create a new scope with the procedure proc defined. ret will be evaluated under this new scope.

When this expression is finished evaluating, proc will be removed from the scope.

-

source

pub fn let_procs(procs: BTreeMap<&str, Procedure>, ret: impl Into<Self>) -> Self

Create several proc bindings at onces.

-
source

pub fn structure(vars: BTreeMap<&str, Self>) -> Self

Create a structure of fields to expressions.

-
source

pub fn var(var: impl ToString) -> Self

Evaluate a variable in the current scope.

-
source

pub fn app(self, args: Vec<Self>) -> Self

Apply this expression as a procedure to some arguments.

-
source

pub fn if_then(self, t: impl Into<Self>, e: impl Into<Self>) -> Self

Create an if-then-else statement with this expression as the condition.

-
source

pub fn while_loop(self, body: impl Into<Self>) -> Self

Create a while statement with this expression as the condition.

-
source

pub fn refer(self, mutability: impl Into<Mutability>) -> Self

Reference this expression (i.e. get a pointer to it).

-
source

pub fn deref(self) -> Self

Dereference this expression (i.e. get the value it points to).

-
source

pub fn deref_mut(self, e: impl Into<Self>) -> Self

Dereference this expression (i.e. get the value it points to), +

source

pub fn let_procs(procs: BTreeMap<&str, Procedure>, ret: impl Into<Self>) -> Self

Create several proc bindings at onces.

+
source

pub fn structure(vars: BTreeMap<&str, Self>) -> Self

Create a structure of fields to expressions.

+
source

pub fn var(var: impl ToString) -> Self

Evaluate a variable in the current scope.

+
source

pub fn app(self, args: Vec<Self>) -> Self

Apply this expression as a procedure to some arguments.

+
source

pub fn if_then(self, t: impl Into<Self>, e: impl Into<Self>) -> Self

Create an if-then-else statement with this expression as the condition.

+
source

pub fn while_loop(self, body: impl Into<Self>) -> Self

Create a while statement with this expression as the condition.

+
source

pub fn refer(self, mutability: impl Into<Mutability>) -> Self

Reference this expression (i.e. get a pointer to it).

+
source

pub fn deref(self) -> Self

Dereference this expression (i.e. get the value it points to).

+
source

pub fn deref_mut(self, e: impl Into<Self>) -> Self

Dereference this expression (i.e. get the value it points to), and write another expression to its position in memory.

-
source

pub fn assign_op(self, op: impl ToString, e: impl Into<Self>) -> Self

Perform an AssignOp on this expression.

-
source

pub fn assign(self, op: impl ToString, e: impl Into<Self>) -> Self

Perform an AssignOp on this expression.

+
source

pub fn assign_op(self, op: impl ToString, e: impl Into<Self>) -> Self

Perform an AssignOp on this expression.

+
source

pub fn assign(self, op: impl ToString, e: impl Into<Self>) -> Self

Perform an AssignOp on this expression.

Trait Implementations§

source§

impl Clone for Expr

source§

fn clone(&self) -> Expr

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Compile for Expr

Compile an LIR expression into several core assembly instructions.

source§

fn compile_expr( self, @@ -173,21 +173,21 @@ output: &mut dyn AssemblyProgram ) -> Result<(), Error>

source§

fn compile(self) -> Result<Result<CoreProgram, StandardProgram>, Error>
where Self: Sized + Clone,

Compile the expression into an assembly program. Read more
source§

impl Debug for Expr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Expr

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Expr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<ConstExpr> for Expr

source§

fn from(c: ConstExpr) -> Self

Converts to this type from the input type.
source§

impl GetType for Expr

Infer the type associated with an expression under a given environment.

-
source§

fn substitute(&mut self, name: &str, ty: &Type)

Substitute a type in a given expression.

-
source§

fn get_type_checked(&self, env: &Env, i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check -recursion depth to prevent a possible stack overflow.
source§

fn get_type(&self, env: &Env) -> Result<Type, Error>

Get the type associated with a value under a given environment.
source§

fn substitute_types(&mut self, names: &[String], types: &[Type])

source§

impl Hash for Expr

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Expr

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<ConstExpr> for Expr

source§

fn from(c: ConstExpr) -> Self

Converts to this type from the input type.
source§

impl GetType for Expr

Infer the type associated with an expression under a given environment.

+
source§

fn substitute(&mut self, name: &str, ty: &Type)

Substitute a type in a given expression.

+
source§

fn get_type_checked(&self, env: &Env, i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check +recursion depth to prevent a possible stack overflow.
source§

fn get_type(&self, env: &Env) -> Result<Type, Error>

Get the type associated with a value under a given environment.
source§

fn substitute_types(&mut self, names: &[String], types: &[Type])

source§

impl Hash for Expr

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, - Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl PartialEq for Expr

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used + Self: Sized,
Feeds a slice of this type into the given Hasher. Read more
source§

impl PartialEq for Expr

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Serialize for Expr

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where - __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl TypeCheck for Expr

Check the type-soundness of a given expression.

-
source§

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.

Auto Trait Implementations§

§

impl RefUnwindSafe for Expr

§

impl Send for Expr

§

impl Sync for Expr

§

impl Unpin for Expr

§

impl UnwindSafe for Expr

Blanket Implementations§

source§

impl<T> Any for T
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl TypeCheck for Expr

Check the type-soundness of a given expression.

+
source§

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.

Auto Trait Implementations§

§

impl RefUnwindSafe for Expr

§

impl Send for Expr

§

impl Sync for Expr

§

impl Unpin for Expr

§

impl UnwindSafe for Expr

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

-
source§

impl<T> GetSize for T
where - T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive +
source§

impl<T> GetSize for T
where + T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive calls to prevent stack overflow. i is a counter to prevent infinite recursion.
source§

fn get_size(&self, env: &Env) -> Result<usize, Error>

Get the size of something in memory (number of cells).
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

diff --git a/docs/sage/lir/enum.Mutability.html b/docs/sage/lir/enum.Mutability.html index 6beb9c79..9133f124 100644 --- a/docs/sage/lir/enum.Mutability.html +++ b/docs/sage/lir/enum.Mutability.html @@ -21,9 +21,9 @@

Trait Implementations§

source§

impl Clone for Mutability

source§

fn clone(&self) -> Mutability

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Mutability

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Mutability

source§

fn default() -> Mutability

Returns the “default value” for a type. Read more
source§

impl<'de> Deserialize<'de> for Mutability

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Mutability

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<Mutability> for bool

Convert a mutability into a boolean. It will return true if the data is mutable (or any), and false if it is immutable.

-
source§

fn from(m: Mutability) -> Self

Converts to this type from the input type.
source§

impl From<bool> for Mutability

Convert a boolean into a mutability. +

source§

fn from(m: Mutability) -> Self

Converts to this type from the input type.
source§

impl From<bool> for Mutability

Convert a boolean into a mutability. True is mutable, false is immutable.

-
source§

fn from(b: bool) -> Self

Converts to this type from the input type.
source§

impl Hash for Mutability

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +
source§

fn from(b: bool) -> Self

Converts to this type from the input type.

source§

impl Hash for Mutability

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for Mutability

source§

fn cmp(&self, other: &Mutability) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/lir/enum.Pattern.html b/docs/sage/lir/enum.Pattern.html index b0b633db..bd43e1ef 100644 --- a/docs/sage/lir/enum.Pattern.html +++ b/docs/sage/lir/enum.Pattern.html @@ -84,8 +84,8 @@ defining the bindings in the environment to map to the correct position in the stack relative to the expression. If the expression and pattern differ in size or type, then this will not work correctly. This function does not check the arguments.

-

Trait Implementations§

source§

impl Clone for Pattern

source§

fn clone(&self) -> Pattern

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Pattern

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Pattern

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Pattern

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Pattern

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Trait Implementations§

source§

impl Clone for Pattern

source§

fn clone(&self) -> Pattern

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Pattern

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Pattern

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Pattern

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Pattern

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl PartialEq for Pattern

source§

fn eq(&self, other: &Pattern) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always diff --git a/docs/sage/lir/enum.Put.html b/docs/sage/lir/enum.Put.html index 79dac75f..bf893341 100644 --- a/docs/sage/lir/enum.Put.html +++ b/docs/sage/lir/enum.Put.html @@ -1,43 +1,43 @@ Put in sage::lir - Rust -

Enum sage::lir::Put

source ·
pub enum Put {
+    

Enum sage::lir::Put

source ·
pub enum Put {
     Debug,
     Display,
 }
Expand description

Print a value to a given output.

-

Variants§

§

Debug

§

Display

Implementations§

source§

impl Put

source

pub fn debug( +

Variants§

§

Debug

§

Display

Implementations§

source§

impl Put

source

pub fn debug( addr: Location, t: &Type, env: &mut Env, output: &mut dyn AssemblyProgram -) -> Result<(), Error>

source

pub fn display( +) -> Result<(), Error>

source

pub fn display( addr: Location, t: &Type, env: &mut Env, output: &mut dyn AssemblyProgram -) -> Result<(), Error>

Trait Implementations§

source§

impl Clone for Put

source§

fn clone(&self) -> Put

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Put

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Put

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Put

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +) -> Result<(), Error>

Trait Implementations§

source§

impl Clone for Put

source§

fn clone(&self) -> Put

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Put

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Put

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Put

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, - Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for Put

source§

fn cmp(&self, other: &Put) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for Put

source§

fn cmp(&self, other: &Put) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where - Self: Sized + PartialOrd,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for Put

source§

fn eq(&self, other: &Put) -> bool

This method tests for self and other values to be equal, and is used + Self: Sized + PartialOrd,
Restrict a value to a certain interval. Read more
source§

impl PartialEq for Put

source§

fn eq(&self, other: &Put) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for Put

source§

fn partial_cmp(&self, other: &Put) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for Put

source§

fn partial_cmp(&self, other: &Put) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
source§

impl UnaryOp for Put

source§

fn can_apply(&self, _expr: &Type, _env: &Env) -> Result<bool, Error>

Can this unary operation be applied to the given type?

-
source§

fn return_type(&self, _expr: &Expr, _env: &Env) -> Result<Type, Error>

Get the type of the result of applying this unary operation to the given type.

-
source§

fn eval(&self, _expr: &ConstExpr, _env: &mut Env) -> Result<ConstExpr, Error>

Evaluate this unary operation on the given constant values.

-
source§

fn compile_types( +operator. Read more

source§

impl UnaryOp for Put

source§

fn can_apply(&self, _expr: &Type, _env: &Env) -> Result<bool, Error>

Can this unary operation be applied to the given type?

+
source§

fn return_type(&self, _expr: &Expr, _env: &Env) -> Result<Type, Error>

Get the type of the result of applying this unary operation to the given type.

+
source§

fn eval(&self, _expr: &ConstExpr, _env: &mut Env) -> Result<ConstExpr, Error>

Evaluate this unary operation on the given constant values.

+
source§

fn compile_types( &self, ty: &Type, env: &mut Env, output: &mut dyn AssemblyProgram ) -> Result<(), Error>

Compile the unary operation.

-
source§

fn clone_box(&self) -> Box<dyn UnaryOp>

Clone this operation into a box.

+
source§

fn clone_box(&self) -> Box<dyn UnaryOp>

Clone this operation into a box.

source§

fn name(&self) -> String

source§

fn type_check(&self, expr: &Expr, env: &Env) -> Result<(), Error>

Typechecks the operation on the given expression.
source§

fn display(&self, expr: &Expr) -> String

Formats the operation for display.
source§

fn can_apply_exprs(&self, expr: &Expr, env: &Env) -> Result<bool, Error>

Checks if the operation can be applied to the given expression.
source§

fn compile( &self, expr: &Expr, env: &mut Env, output: &mut dyn AssemblyProgram -) -> Result<(), Error>

Compiles the operation on the given expression.
source§

impl Copy for Put

source§

impl Eq for Put

source§

impl StructuralEq for Put

source§

impl StructuralPartialEq for Put

Auto Trait Implementations§

§

impl RefUnwindSafe for Put

§

impl Send for Put

§

impl Sync for Put

§

impl Unpin for Put

§

impl UnwindSafe for Put

Blanket Implementations§

source§

impl<T> Any for T
where +) -> Result<(), Error>

Compiles the operation on the given expression.
source§

impl Copy for Put

source§

impl Eq for Put

source§

impl StructuralEq for Put

source§

impl StructuralPartialEq for Put

Auto Trait Implementations§

§

impl RefUnwindSafe for Put

§

impl Send for Put

§

impl Sync for Put

§

impl Unpin for Put

§

impl UnwindSafe for Put

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/docs/sage/lir/enum.Type.html b/docs/sage/lir/enum.Type.html index 7db0d8a7..d102c4e5 100644 --- a/docs/sage/lir/enum.Type.html +++ b/docs/sage/lir/enum.Type.html @@ -1,6 +1,6 @@ -Type in sage::lir - Rust -

Enum sage::lir::Type

source ·
pub enum Type {
-
Show 22 variants Let(String, Box<Self>, Box<Self>), +Type in sage::lir - Rust +

Enum sage::lir::Type

source ·
pub enum Type {
+
Show 23 variants Let(String, Box<Self>, Box<Self>), Unit(String, Box<Self>), Symbol(String), None, @@ -20,8 +20,9 @@ Pointer(Mutability, Box<Self>), Any, Never, - Poly(Vec<String>, Box<Self>), + Poly(Vec<(String, Option<Type>)>, Box<Self>), Apply(Box<Self>, Vec<Self>), + ConstParam(Box<ConstExpr>),
}
Expand description

The representation of a type in the LIR type system.

Variants§

§

Let(String, Box<Self>, Box<Self>)

Bind a type to a name in a temporary scope.

§

Unit(String, Box<Self>)

This type is identified by its name. Most types are checked according @@ -59,28 +60,41 @@ This type is equal to any other type. The NULL pointer, for example, is of type Pointer(Any).

§

Never

The type of an expression that will never return, or doesn’t resolve to a value.

-
§

Poly(Vec<String>, Box<Self>)

A polymorphic, parametric type. +

§

Poly(Vec<(String, Option<Type>)>, Box<Self>)

A polymorphic, parametric type. This type is used with the Apply type to create a concrete type. The type takes a list of symbols that are substituted with concrete types. The type is then simplified to a concrete type when combined with Apply. This type is used to implement generics.

§

Apply(Box<Self>, Vec<Self>)

A type that constructs a concrete type from a polymorphic type. This type is used to implement generics.

-

Implementations§

source§

impl Type

source

pub const SIMPLIFY_RECURSION_LIMIT: usize = 30usize

This is the maximum number of times a type will be simplified recursively.

-
source

pub fn is_recursive(&self, env: &Env) -> Result<bool, Error>

source

pub fn is_recursive_helper( +

§

ConstParam(Box<ConstExpr>)

A constant literal used in a type expression, like a template application +with a constant parameter.

+

Implementations§

source§

impl Type

source

pub const SIMPLIFY_RECURSION_LIMIT: usize = 30usize

This is the maximum number of times a type will be simplified recursively.

+
source

pub fn is_recursive(&self, env: &Env) -> Result<bool, Error>

source

pub fn is_const_param(&self) -> bool

Is this type a constant parameter?

+

This will recursively detect if the subtypes are constant parameters as well

+
source

pub fn is_recursive_helper( &self, symbols: &mut HashSet<String>, env: &Env -) -> Result<bool, Error>

source

pub fn strip_template(&self, env: &Env) -> Self

source

pub fn is_poly(&self) -> bool

source

pub fn get_monomorph_template_args( +) -> Result<bool, Error>

Is this type recursive?

+
source

pub fn strip_template(&self, env: &Env) -> Self

Strip the template arguments to get the inner type

+
source

pub fn is_poly(&self) -> bool

Is this a polymorphic function?

+
source

pub fn get_monomorph_template_args( &self, template: &Self, - matched_symbols: &mut HashMap<String, Self>, + matched_symbols: &mut HashMap<String, (Self, Option<Type>)>, param_symbols: &HashSet<String>, env: &Env -) -> Result<(), Error>

source

pub fn is_monomorph_of(&self, template: &Self, env: &Env) -> Result<bool, Error>

source

pub fn add_monomorphized_associated_consts( +) -> Result<(), Error>

Get the template arguments for the monomorph (this type) of some polymorphic base type. +This will match the symbols in the template against the monomorph.

+
source

pub fn is_monomorph_of(&self, template: &Self, env: &Env) -> Result<bool, Error>

Is this type a monomorph of a given template type?

+
source

pub fn add_monomorphized_associated_consts( &self, env: &Env -) -> Result<(), Error>

source

pub fn get_template_params(&self, env: &Env) -> Vec<String>

source

pub fn apply(&self, args: Vec<Self>) -> Self

source

pub fn is_simple(&self) -> bool

Is this type in a simple form? +) -> Result<(), Error>

Add monomorphized methods for a given monomorph of a template type with methods.

+
source

pub fn get_template_params(&self, env: &Env) -> Vec<(String, Option<Type>)>

Get the template parameters for this template type.

+
source

pub fn apply(&self, args: Vec<Self>) -> Self

Apply this template type with some type arguments.

+
source

pub fn is_simple(&self) -> bool

Is this type in a simple form? A simple form is a form that does not require any immediate simplification. For example, a Poly type is not simple, because it requires a Apply type to deduce anything about the type. A let binding is also not simple, because @@ -88,62 +102,100 @@ because it requires a lookup in the environment to determine the type. Other types, like a tagged union, which may be pattern matched over the inner types, does not require an immediate lookup to use some of its type information.

-
source

pub fn is_concrete(&self) -> bool

source

pub fn is_atomic(&self) -> bool

Is this type an irreducible, atomic type?

-
source

pub fn is_self_param_reference(&self, env: &Env) -> Result<bool, Error>

Is first argument of function a reference?

-
source

pub fn get_self_param_mutability(&self, env: &Env) -> Option<Mutability>

Get the first argument’s mutability (if it is a pointer)

-
source

pub fn simplify_until_type_checks(&self, env: &Env) -> Result<Self, Error>

Simplify until the type passes the type checker.

-
source

pub fn simplify_until_has_members(&self, env: &Env) -> Result<Self, Error>

Simplify a type until you can get its members.

-
source

pub fn simplify_until_union(&self, env: &Env) -> Result<Self, Error>

Simplify a type until it’s a union.

-
source

pub fn simplify_until_has_variants(&self, env: &Env) -> Result<Self, Error>

Simplify a type until you can get its variants.

-
source

pub fn simplify_until_atomic(&self, env: &Env) -> Result<Self, Error>

source

pub fn simplify_until_simple(&self, env: &Env) -> Result<Self, Error>

source

pub fn simplify_until_poly(&self, env: &Env) -> Result<Self, Error>

Simplify until the type is a polymorphic type.

-
source

pub fn simplify_until_concrete(&self, env: &Env) -> Result<Self, Error>

Simplify until the type is concrete.

-
source

pub fn simplify_until_matches( +

source

pub fn is_concrete(&self) -> bool

Is this type simplified enough to get information about what the +outer type is? Is it a tuple, a struct, etc?

+

Symbols and polymorphic types do not satisfy this condition.

+
source

pub fn is_atomic(&self) -> bool

Is this type an irreducible, atomic type?

+
source

pub fn is_self_param_reference(&self, env: &Env) -> Result<bool, Error>

Is first argument of function a reference?

+
source

pub fn get_self_param_mutability(&self, env: &Env) -> Option<Mutability>

Get the first argument’s mutability (if it is a pointer)

+
source

pub fn simplify_until_type_checks(&self, env: &Env) -> Result<Self, Error>

Simplify until the type passes the type checker.

+
source

pub fn simplify_until_has_members( + &self, + env: &Env, + checked: bool +) -> Result<Self, Error>

Simplify a type until you can get its members.

+
source

pub fn simplify_until_union( + &self, + env: &Env, + checked: bool +) -> Result<Self, Error>

Simplify a type until it’s a union.

+
source

pub fn simplify_until_has_variants( + &self, + env: &Env, + checked: bool +) -> Result<Self, Error>

Simplify a type until you can get its variants.

+
source

pub fn simplify_until_atomic( + &self, + env: &Env, + checked: bool +) -> Result<Self, Error>

source

pub fn simplify_until_simple( + &self, + env: &Env, + checked: bool +) -> Result<Self, Error>

source

pub fn simplify_until_poly( + &self, + env: &Env, + checked: bool +) -> Result<Self, Error>

Simplify until the type is a polymorphic type.

+
source

pub fn simplify_until_concrete( + &self, + env: &Env, + checked: bool +) -> Result<Self, Error>

Simplify until the type is concrete.

+
source

pub fn simplify_until_const_param( + &self, + env: &Env, + _checked: bool +) -> Result<ConstExpr, Error>

Simplify until the type is concrete.

+
source

pub fn simplify_until_matches( self, env: &Env, expected: Self, - f: impl Fn(&Self, &Env) -> Result<bool, Error> + f: impl Fn(&Self, &Env) -> Result<bool, Error>, + checked: bool ) -> Result<Self, Error>

Simplify an expression until it matches a given function which “approves” of a type. This will perform template applications to simplify the type if possible as well.

This is usually too verbose to be used on its own, better to make a wrapper function that calls this with a more specific use case/purpose.

-
source

pub fn let_bind(name: &str, t: Self, ret: Self) -> Self

Create a let-bound type.

-
source

pub fn variant_index(variants: &[String], variant: &String) -> Option<usize>

Calculate the integral value of a variant in an enum.

-
source

pub fn contains_symbol(&self, name: &str) -> bool

Does this type contain a symbol with the given name? +

source

pub fn let_bind(name: &str, t: Self, ret: Self) -> Self

Create a let-bound type.

+
source

pub fn variant_index(variants: &[String], variant: &String) -> Option<usize>

Calculate the integral value of a variant in an enum.

+
source

pub fn contains_symbol(&self, name: &str) -> bool

Does this type contain a symbol with the given name? This will not count overshadowded versions of the symbol (overwritten by let-bindings).

-
source

pub fn substitute(&self, name: &str, substitution: &Self) -> Self

Substitute all occurences of a symbol with another type. +

source

pub fn substitute(&self, name: &str, substitution: &Self) -> Self

Substitute all occurences of a symbol with another type. This will not traverse into let-bindings when the symbol is overshadowed.

-
source

pub fn has_element_type(&self, element: &Self, env: &Env) -> Result<bool, Error>

Does this type have an element type matching the supplied type? +

source

pub fn has_element_type(&self, element: &Self, env: &Env) -> Result<bool, Error>

Does this type have an element type matching the supplied type? If this type is an array of Integers, for example, then this function will return true if the supplied type is an Integer.

-
source

pub fn can_decay_to(&self, desired: &Self, env: &Env) -> Result<bool, Error>

Can this type decay into another type?

+
source

pub fn can_decay_to(&self, desired: &Self, env: &Env) -> Result<bool, Error>

Can this type decay into another type?

A type can decay into another type if the compiler can automatically convert the type into the other type. This is distinct from the compiler seeing the types as equal. The two types are not equal; the compiler will just automatically perform the conversion.

For all cases right now, a decay does nothing; the representations of the types in the compiler are the same for all types of decay.

-
source

pub fn can_cast_to(&self, other: &Self, env: &Env) -> Result<bool, Error>

Can this type be cast to another type?

-
source

pub fn equals(&self, other: &Self, env: &Env) -> Result<bool, Error>

Are two types structurally equal?

-
source

pub fn perform_template_applications( +

source

pub fn can_cast_to(&self, other: &Self, env: &Env) -> Result<bool, Error>

Can this type be cast to another type?

+
source

pub fn equals(&self, other: &Self, env: &Env) -> Result<bool, Error>

Are two types structurally equal?

+
source

pub fn perform_template_applications( &self, env: &Env, - previous_applications: &mut HashMap<(Type, Vec<Type>), Type> + previous_applications: &mut HashMap<(Type, Vec<Type>), Type>, + checked: bool ) -> Result<Self, Error>

Perform type applications if possible.

Trait Implementations§

source§

impl Clone for Type

source§

fn clone(&self) -> Type

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Type

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Type

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Type

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl GetSize for Type

Calculate the size of a type in units of cells.

-
source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive + __D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Type

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<Type> for ConstExpr

source§

fn from(value: Type) -> Self

Converts to this type from the input type.
source§

impl GetSize for Type

Calculate the size of a type in units of cells.

+
source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive calls to prevent stack overflow. i is a counter to prevent infinite -recursion.
source§

fn get_size(&self, env: &Env) -> Result<usize, Error>

Get the size of something in memory (number of cells).
source§

impl Hash for Type

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +recursion.

source§

fn get_size(&self, env: &Env) -> Result<usize, Error>

Get the size of something in memory (number of cells).
source§

impl Hash for Type

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl PartialEq for Type

source§

fn eq(&self, other: &Type) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Serialize for Type

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where - __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl Simplify for Type

source§

fn simplify_checked(self, env: &Env, i: usize) -> Result<Self, Error>

Simplify an expression while maintaining structural equality, but limit + __S: Serializer,
Serialize this value into the given Serde serializer. Read more
source§

impl Simplify for Type

source§

fn simplify_checked(self, env: &Env, i: usize) -> Result<Self, Error>

Simplify an expression while maintaining structural equality, but limit the number of recursive calls to prevent stack overflow. i is a -counter to prevent infinite recursion.
source§

fn simplify(self, env: &Env) -> Result<Self, Error>

Simplify an expression while maintaining structural equality.
source§

impl TypeCheck for Type

Check the soundness of a given type in the environment.

-
source§

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.
source§

impl Eq for Type

source§

impl Send for Type

source§

impl StructuralPartialEq for Type

source§

impl Sync for Type

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where +counter to prevent infinite recursion.

source§

fn simplify(self, env: &Env) -> Result<Self, Error>

Simplify an expression while maintaining structural equality.
source§

impl TypeCheck for Type

Check the soundness of a given type in the environment.

+
source§

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.
source§

impl Eq for Type

source§

impl Send for Type

source§

impl StructuralPartialEq for Type

source§

impl Sync for Type

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where - T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+ T: ?Sized,
source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of diff --git a/docs/sage/lir/struct.And.html b/docs/sage/lir/struct.And.html index d30666eb..f201eeed 100644 --- a/docs/sage/lir/struct.And.html +++ b/docs/sage/lir/struct.And.html @@ -32,7 +32,7 @@ rhs: &Expr, env: &mut Env, output: &mut dyn AssemblyProgram -) -> Result<(), Error>

Compiles the operation on the given expressions.
source§

impl Clone for And

source§

fn clone(&self) -> And

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for And

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for And

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for And

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +) -> Result<(), Error>

Compiles the operation on the given expressions.
source§

impl Clone for And

source§

fn clone(&self) -> And

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for And

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for And

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for And

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for And

source§

fn cmp(&self, other: &And) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/lir/struct.Assign.html b/docs/sage/lir/struct.Assign.html index 8911781b..ac7aa77e 100644 --- a/docs/sage/lir/struct.Assign.html +++ b/docs/sage/lir/struct.Assign.html @@ -34,7 +34,7 @@ dst: &Expr, src: &Expr, env: &Env -) -> Result<bool, Error>

Checks if the operation can be applied to the given expressions.
source§

impl Clone for Assign

source§

fn clone(&self) -> Assign

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Assign

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Assign

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Assign

§

impl Send for Assign

§

impl Sync for Assign

§

impl Unpin for Assign

§

impl !UnwindSafe for Assign

Blanket Implementations§

source§

impl<T> Any for T
where +) -> Result<bool, Error>

Checks if the operation can be applied to the given expressions.
source§

impl Clone for Assign

source§

fn clone(&self) -> Assign

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Assign

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Assign

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Assign

§

impl Send for Assign

§

impl Sync for Assign

§

impl Unpin for Assign

§

impl !UnwindSafe for Assign

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/docs/sage/lir/struct.BitwiseAnd.html b/docs/sage/lir/struct.BitwiseAnd.html index 0c4e3200..d614421f 100644 --- a/docs/sage/lir/struct.BitwiseAnd.html +++ b/docs/sage/lir/struct.BitwiseAnd.html @@ -27,7 +27,7 @@ rhs: &Expr, env: &mut Env, output: &mut dyn AssemblyProgram -) -> Result<(), Error>
Compiles the operation on the given expressions.
source§

impl Clone for BitwiseAnd

source§

fn clone(&self) -> BitwiseAnd

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for BitwiseAnd

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for BitwiseAnd

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for BitwiseAnd

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +) -> Result<(), Error>

Compiles the operation on the given expressions.
source§

impl Clone for BitwiseAnd

source§

fn clone(&self) -> BitwiseAnd

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for BitwiseAnd

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for BitwiseAnd

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for BitwiseAnd

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for BitwiseAnd

source§

fn cmp(&self, other: &BitwiseAnd) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/lir/struct.BitwiseNor.html b/docs/sage/lir/struct.BitwiseNor.html index adb87caf..89b68b5d 100644 --- a/docs/sage/lir/struct.BitwiseNor.html +++ b/docs/sage/lir/struct.BitwiseNor.html @@ -27,7 +27,7 @@ rhs: &Expr, env: &mut Env, output: &mut dyn AssemblyProgram -) -> Result<(), Error>

Compiles the operation on the given expressions.
source§

impl Clone for BitwiseNor

source§

fn clone(&self) -> BitwiseNor

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for BitwiseNor

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for BitwiseNor

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for BitwiseNor

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +) -> Result<(), Error>

Compiles the operation on the given expressions.
source§

impl Clone for BitwiseNor

source§

fn clone(&self) -> BitwiseNor

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for BitwiseNor

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for BitwiseNor

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for BitwiseNor

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for BitwiseNor

source§

fn cmp(&self, other: &BitwiseNor) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/lir/struct.BitwiseNot.html b/docs/sage/lir/struct.BitwiseNot.html index c5ae3727..711c08f9 100644 --- a/docs/sage/lir/struct.BitwiseNot.html +++ b/docs/sage/lir/struct.BitwiseNot.html @@ -1,5 +1,5 @@ BitwiseNot in sage::lir - Rust -

Struct sage::lir::BitwiseNot

source ·
pub struct BitwiseNot;

Trait Implementations§

source§

impl Clone for BitwiseNot

source§

fn clone(&self) -> BitwiseNot

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for BitwiseNot

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for BitwiseNot

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for BitwiseNot

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Struct sage::lir::BitwiseNot

source ·
pub struct BitwiseNot;

Trait Implementations§

source§

impl Clone for BitwiseNot

source§

fn clone(&self) -> BitwiseNot

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for BitwiseNot

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for BitwiseNot

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for BitwiseNot

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for BitwiseNot

source§

fn cmp(&self, other: &BitwiseNot) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/lir/struct.CoreBuiltin.html b/docs/sage/lir/struct.CoreBuiltin.html index 12ff8e33..1d4c06dc 100644 --- a/docs/sage/lir/struct.CoreBuiltin.html +++ b/docs/sage/lir/struct.CoreBuiltin.html @@ -18,8 +18,8 @@ _env: &mut Env, output: &mut dyn AssemblyProgram ) -> Result<(), Error>

source§

fn compile(self) -> Result<Result<CoreProgram, StandardProgram>, Error>
where - Self: Sized + Clone,

Compile the expression into an assembly program. Read more
source§

impl Debug for CoreBuiltin

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for CoreBuiltin

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for CoreBuiltin

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl GetType for CoreBuiltin

source§

fn get_type_checked(&self, _env: &Env, _i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check + Self: Sized + Clone,

Compile the expression into an assembly program. Read more
source§

impl Debug for CoreBuiltin

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for CoreBuiltin

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for CoreBuiltin

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl GetType for CoreBuiltin

source§

fn get_type_checked(&self, _env: &Env, _i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check recursion depth to prevent a possible stack overflow.
source§

fn substitute(&mut self, name: &str, ty: &Type)

Substitute a type for a given name in the environment.
source§

fn get_type(&self, env: &Env) -> Result<Type, Error>

Get the type associated with a value under a given environment.
source§

fn substitute_types(&mut self, names: &[String], types: &[Type])

source§

impl Hash for CoreBuiltin

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl PartialEq for CoreBuiltin

source§

fn eq(&self, other: &CoreBuiltin) -> bool

This method tests for self and other values to be equal, and is used @@ -29,8 +29,8 @@ T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

-
source§

impl<T> GetSize for T
where - T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive +
source§

impl<T> GetSize for T
where + T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive calls to prevent stack overflow. i is a counter to prevent infinite recursion.
source§

fn get_size(&self, env: &Env) -> Result<usize, Error>

Get the size of something in memory (number of cells).
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

diff --git a/docs/sage/lir/struct.Data.html b/docs/sage/lir/struct.Data.html index 63d1cb04..7aec1ddb 100644 --- a/docs/sage/lir/struct.Data.html +++ b/docs/sage/lir/struct.Data.html @@ -1,6 +1,6 @@ Data in sage::lir - Rust

Struct sage::lir::Data

source ·
pub struct Data;
Expand description

Get the Union data associated with a tagged union (EnumUnion).

-

Trait Implementations§

source§

impl Clone for Data

source§

fn clone(&self) -> Data

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Data

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Data

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Data

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Trait Implementations§

source§

impl Clone for Data

source§

fn clone(&self) -> Data

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Data

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Data

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Data

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for Data

source§

fn cmp(&self, other: &Data) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/lir/struct.Env.html b/docs/sage/lir/struct.Env.html index 9771d411..67ba683b 100644 --- a/docs/sage/lir/struct.Env.html +++ b/docs/sage/lir/struct.Env.html @@ -1,35 +1,36 @@ Env in sage::lir - Rust

Struct sage::lir::Env

source ·
pub struct Env { /* private fields */ }
Expand description

An environment under which expressions and types are compiled and typechecked. This is essentially the scope of an expression.

-

Implementations§

source§

impl Env

Implementations§

source§

impl Env

source

pub fn get_type_of_associated_const( &self, ty: &Type, name: &str ) -> Option<Type>

Get the type of an associated constant of a type.

-
source

pub fn get_associated_const( +

source

pub fn get_associated_const( &self, ty: &Type, name: &str -) -> Option<(ConstExpr, Type)>

source

pub fn has_associated_const(&self, ty: &Type, name: &str) -> bool

source

pub fn get_all_associated_consts(&self, ty: &Type) -> Vec<(String, ConstExpr)>

source

pub fn add_associated_const( +) -> Option<(ConstExpr, Type)>

source

pub fn has_associated_const(&self, ty: &Type, name: &str) -> bool

source

pub fn get_all_associated_consts(&self, ty: &Type) -> Vec<(String, ConstExpr)>

source

pub fn add_associated_const( &self, ty: Type, associated_const_name: impl ToString, expr: ConstExpr -) -> Result<(), Error>

source

pub fn define_types(&mut self, types: Vec<(String, Type)>)

Define multiple types with the given names under this environment.

+) -> Result<(), Error>

source

pub fn define_types(&mut self, types: Vec<(String, Type)>)

Define multiple types with the given names under this environment.

This must be used in situations where the different types depend on each other. This is because the sizes of types are memoized, and this will interfere with the memoization process if the types are defined separately. It will lead to typechecking errors if the environment does not already have a memoized size for the type of a subexpression.

-
source

pub fn define_var( +

source

pub fn define_var( &mut self, var: impl ToString, mutability: Mutability, - ty: Type + ty: Type, + compiling: bool ) -> Result<isize, Error>

Define a variable in the current scope. This will increment the scope’s frame pointer offset by the size of the variable. This method returns the offset of the variable from the frame pointer under this scope.

-

Trait Implementations§

source§

impl Clone for Env

source§

fn clone(&self) -> Env

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Env

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Env

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl Display for Env

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Env

§

impl Send for Env

§

impl Sync for Env

§

impl Unpin for Env

§

impl !UnwindSafe for Env

Blanket Implementations§

source§

impl<T> Any for T
where +

Trait Implementations§

source§

impl Clone for Env

source§

fn clone(&self) -> Env

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Env

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Env

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl Display for Env

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Env

§

impl Send for Env

§

impl Sync for Env

§

impl Unpin for Env

§

impl !UnwindSafe for Env

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/docs/sage/lir/struct.FFIProcedure.html b/docs/sage/lir/struct.FFIProcedure.html index a04554db..21fc1b8b 100644 --- a/docs/sage/lir/struct.FFIProcedure.html +++ b/docs/sage/lir/struct.FFIProcedure.html @@ -9,8 +9,8 @@ env: &mut Env, output: &mut dyn AssemblyProgram ) -> Result<(), Error>
source§

fn compile(self) -> Result<Result<CoreProgram, StandardProgram>, Error>
where - Self: Sized + Clone,

Compile the expression into an assembly program. Read more
source§

impl Debug for FFIProcedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for FFIProcedure

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for FFIProcedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl GetType for FFIProcedure

source§

fn get_type_checked(&self, _env: &Env, _i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check + Self: Sized + Clone,
Compile the expression into an assembly program. Read more
source§

impl Debug for FFIProcedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for FFIProcedure

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for FFIProcedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl GetType for FFIProcedure

source§

fn get_type_checked(&self, _env: &Env, _i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check recursion depth to prevent a possible stack overflow.
source§

fn substitute(&mut self, name: &str, substitution: &Type)

Substitute a type for a given name in the environment.
source§

fn get_type(&self, env: &Env) -> Result<Type, Error>

Get the type associated with a value under a given environment.
source§

fn substitute_types(&mut self, names: &[String], types: &[Type])

source§

impl Hash for FFIProcedure

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl PartialEq for FFIProcedure

source§

fn eq(&self, other: &FFIProcedure) -> bool

This method tests for self and other values to be equal, and is used @@ -20,8 +20,8 @@ T: 'static + ?Sized,
source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

-
source§

impl<T> GetSize for T
where - T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive +
source§

impl<T> GetSize for T
where + T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive calls to prevent stack overflow. i is a counter to prevent infinite recursion.
source§

fn get_size(&self, env: &Env) -> Result<usize, Error>

Get the size of something in memory (number of cells).
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

diff --git a/docs/sage/lir/struct.Get.html b/docs/sage/lir/struct.Get.html index 60683821..26494904 100644 --- a/docs/sage/lir/struct.Get.html +++ b/docs/sage/lir/struct.Get.html @@ -1,29 +1,29 @@ Get in sage::lir - Rust -

Struct sage::lir::Get

source ·
pub struct Get;

Trait Implementations§

source§

impl Clone for Get

source§

fn clone(&self) -> Get

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Get

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Get

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Get

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Struct sage::lir::Get

source ·
pub struct Get;

Trait Implementations§

source§

impl Clone for Get

source§

fn clone(&self) -> Get

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Get

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Get

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Get

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, - Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for Get

source§

fn cmp(&self, other: &Get) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for Get

source§

fn cmp(&self, other: &Get) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where - Self: Sized + PartialOrd,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for Get

source§

fn eq(&self, other: &Get) -> bool

This method tests for self and other values to be equal, and is used + Self: Sized + PartialOrd,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for Get

source§

fn eq(&self, other: &Get) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for Get

source§

fn partial_cmp(&self, other: &Get) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for Get

source§

fn partial_cmp(&self, other: &Get) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
source§

impl UnaryOp for Get

source§

fn can_apply(&self, ty: &Type, env: &Env) -> Result<bool, Error>

Can this unary operation be applied to the given type?

-
source§

fn return_type(&self, _expr: &Expr, _env: &Env) -> Result<Type, Error>

Get the type of the result of applying this unary operation to the given type.

-
source§

fn eval(&self, expr: &ConstExpr, _env: &mut Env) -> Result<ConstExpr, Error>

Evaluate this unary operation on the given constant values.

-
source§

fn compile_types( +operator. Read more

source§

impl UnaryOp for Get

source§

fn can_apply(&self, ty: &Type, env: &Env) -> Result<bool, Error>

Can this unary operation be applied to the given type?

+
source§

fn return_type(&self, _expr: &Expr, _env: &Env) -> Result<Type, Error>

Get the type of the result of applying this unary operation to the given type.

+
source§

fn eval(&self, expr: &ConstExpr, _env: &mut Env) -> Result<ConstExpr, Error>

Evaluate this unary operation on the given constant values.

+
source§

fn compile_types( &self, ty: &Type, env: &mut Env, output: &mut dyn AssemblyProgram ) -> Result<(), Error>

Compile the unary operation.

-
source§

fn clone_box(&self) -> Box<dyn UnaryOp>

Clone this operation into a box.

+
source§

fn clone_box(&self) -> Box<dyn UnaryOp>

Clone this operation into a box.

source§

fn name(&self) -> String

source§

fn type_check(&self, expr: &Expr, env: &Env) -> Result<(), Error>

Typechecks the operation on the given expression.
source§

fn display(&self, expr: &Expr) -> String

Formats the operation for display.
source§

fn can_apply_exprs(&self, expr: &Expr, env: &Env) -> Result<bool, Error>

Checks if the operation can be applied to the given expression.
source§

fn compile( &self, expr: &Expr, env: &mut Env, output: &mut dyn AssemblyProgram -) -> Result<(), Error>

Compiles the operation on the given expression.
source§

impl Copy for Get

source§

impl Eq for Get

source§

impl StructuralEq for Get

source§

impl StructuralPartialEq for Get

Auto Trait Implementations§

§

impl RefUnwindSafe for Get

§

impl Send for Get

§

impl Sync for Get

§

impl Unpin for Get

§

impl UnwindSafe for Get

Blanket Implementations§

source§

impl<T> Any for T
where +) -> Result<(), Error>

Compiles the operation on the given expression.
source§

impl Copy for Get

source§

impl Eq for Get

source§

impl StructuralEq for Get

source§

impl StructuralPartialEq for Get

Auto Trait Implementations§

§

impl RefUnwindSafe for Get

§

impl Send for Get

§

impl Sync for Get

§

impl Unpin for Get

§

impl UnwindSafe for Get

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/docs/sage/lir/struct.New.html b/docs/sage/lir/struct.New.html index 69da1408..63e7cf0c 100644 --- a/docs/sage/lir/struct.New.html +++ b/docs/sage/lir/struct.New.html @@ -1,5 +1,5 @@ New in sage::lir - Rust -

Struct sage::lir::New

source ·
pub struct New;

Trait Implementations§

source§

impl Clone for New

source§

fn clone(&self) -> New

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for New

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for New

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for New

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Struct sage::lir::New

source ·
pub struct New;

Trait Implementations§

source§

impl Clone for New

source§

fn clone(&self) -> New

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for New

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for New

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for New

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for New

source§

fn cmp(&self, other: &New) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/lir/struct.Not.html b/docs/sage/lir/struct.Not.html index 865b640f..5e641845 100644 --- a/docs/sage/lir/struct.Not.html +++ b/docs/sage/lir/struct.Not.html @@ -1,6 +1,6 @@ Not in sage::lir - Rust

Struct sage::lir::Not

source ·
pub struct Not;
Expand description

A boolean “Not” operation on a value.

-

Trait Implementations§

source§

impl Clone for Not

source§

fn clone(&self) -> Not

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Not

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Not

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl UnaryOp for Not

source§

fn can_apply(&self, expr: &Type, env: &Env) -> Result<bool, Error>

Can this unary operation be applied to the given type?

+

Trait Implementations§

source§

impl Clone for Not

source§

fn clone(&self) -> Not

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Not

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Not

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl UnaryOp for Not

source§

fn can_apply(&self, expr: &Type, env: &Env) -> Result<bool, Error>

Can this unary operation be applied to the given type?

source§

fn return_type(&self, _expr: &Expr, _env: &Env) -> Result<Type, Error>

Get the type of the result of applying this unary operation to the given type.

source§

fn eval(&self, expr: &ConstExpr, env: &mut Env) -> Result<ConstExpr, Error>

Evaluate this unary operation on the given constant values.

source§

fn compile_types( diff --git a/docs/sage/lir/struct.Or.html b/docs/sage/lir/struct.Or.html index a5490ec5..6a39b773 100644 --- a/docs/sage/lir/struct.Or.html +++ b/docs/sage/lir/struct.Or.html @@ -32,7 +32,7 @@ rhs: &Expr, env: &mut Env, output: &mut dyn AssemblyProgram -) -> Result<(), Error>

Compiles the operation on the given expressions.
source§

impl Clone for Or

source§

fn clone(&self) -> Or

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Or

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Or

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Copy for Or

Auto Trait Implementations§

§

impl RefUnwindSafe for Or

§

impl Send for Or

§

impl Sync for Or

§

impl Unpin for Or

§

impl UnwindSafe for Or

Blanket Implementations§

source§

impl<T> Any for T
where +) -> Result<(), Error>

Compiles the operation on the given expressions.
source§

impl Clone for Or

source§

fn clone(&self) -> Or

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Or

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Display for Or

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Copy for Or

Auto Trait Implementations§

§

impl RefUnwindSafe for Or

§

impl Send for Or

§

impl Sync for Or

§

impl Unpin for Or

§

impl UnwindSafe for Or

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/docs/sage/lir/struct.PolyProcedure.html b/docs/sage/lir/struct.PolyProcedure.html index d4912dc1..7ed8f7ce 100644 --- a/docs/sage/lir/struct.PolyProcedure.html +++ b/docs/sage/lir/struct.PolyProcedure.html @@ -1,38 +1,41 @@ -PolyProcedure in sage::lir - Rust +PolyProcedure in sage::lir - Rust

Struct sage::lir::PolyProcedure

source ·
pub struct PolyProcedure { /* private fields */ }
Expand description

A polymorphic procedure of LIR code which can be applied to a list of arguments with type arguments. This is mono-morphed into a Procedure when it is called with a list of type arguments. A procedure is compiled down to a label in the assembly code.

-

Implementations§

source§

impl PolyProcedure

source

pub fn new( +

Implementations§

source§

impl PolyProcedure

source

pub fn new( name: String, - ty_params: Vec<String>, + ty_params: Vec<(String, Option<Type>)>, args: Vec<(String, Mutability, Type)>, ret: Type, body: impl Into<Expr> ) -> Self

Construct a new polymorphic procedure with type parameters, a list of arguments + their types, a return type, and the body of the procedure.

-
source

pub fn with(&self, decls: impl Into<Declaration>) -> Self

source

pub fn from_mono(mono: Procedure, ty_params: Vec<String>) -> Self

source

pub fn get_name(&self) -> &str

Get the name of this polymorphic procedure. +

source

pub fn with(&self, decls: impl Into<Declaration>) -> Self

source

pub fn get_type_params(&self) -> &Vec<(String, Option<Type>)>

source

pub fn from_mono( + mono: Procedure, + ty_params: Vec<(String, Option<Type>)> +) -> Self

source

pub fn get_name(&self) -> &str

Get the name of this polymorphic procedure. This is not the mangled name, but the name known to the LIR front-end. The mangled name is unique for each monomorph of the procedure.

-
source

pub fn monomorphize( +

source

pub fn monomorphize( &self, ty_args: Vec<Type>, env: &Env ) -> Result<Procedure, Error>

Take some type arguments and produce a monomorphized version of the procedure. This monomorphized version can then be compiled directly. Additionally, the mono version of the procedure is memoized, so that it is only compiled once.

-

Trait Implementations§

source§

impl Clone for PolyProcedure

source§

fn clone(&self) -> PolyProcedure

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for PolyProcedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for PolyProcedure

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for PolyProcedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl GetType for PolyProcedure

source§

fn get_type_checked(&self, _env: &Env, _i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check -recursion depth to prevent a possible stack overflow.
source§

fn substitute(&mut self, name: &str, ty: &Type)

Substitute a type for a given name in the environment.
source§

fn get_type(&self, env: &Env) -> Result<Type, Error>

Get the type associated with a value under a given environment.
source§

fn substitute_types(&mut self, names: &[String], types: &[Type])

source§

impl Hash for PolyProcedure

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Trait Implementations§

source§

impl Clone for PolyProcedure

source§

fn clone(&self) -> PolyProcedure

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for PolyProcedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for PolyProcedure

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for PolyProcedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<PolyProcedure> for ConstExpr

source§

fn from(value: PolyProcedure) -> Self

Converts to this type from the input type.
source§

impl GetType for PolyProcedure

source§

fn get_type_checked(&self, _env: &Env, _i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check +recursion depth to prevent a possible stack overflow.
source§

fn substitute(&mut self, name: &str, ty: &Type)

Substitute a type for a given name in the environment.
source§

fn get_type(&self, env: &Env) -> Result<Type, Error>

Get the type associated with a value under a given environment.
source§

fn substitute_types(&mut self, names: &[String], types: &[Type])

source§

impl Hash for PolyProcedure

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl PartialEq for PolyProcedure

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Serialize for PolyProcedure

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where - __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl TypeCheck for PolyProcedure

source§

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.
source§

impl Eq for PolyProcedure

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl TypeCheck for PolyProcedure

source§

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.
source§

impl Eq for PolyProcedure

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where - T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

-
source§

impl<T> GetSize for T
where - T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T> GetSize for T
where + T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive calls to prevent stack overflow. i is a counter to prevent infinite recursion.
source§

fn get_size(&self, env: &Env) -> Result<usize, Error>

Get the size of something in memory (number of cells).
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

diff --git a/docs/sage/lir/struct.Procedure.html b/docs/sage/lir/struct.Procedure.html index 1492b2f3..cc07402e 100644 --- a/docs/sage/lir/struct.Procedure.html +++ b/docs/sage/lir/struct.Procedure.html @@ -1,4 +1,4 @@ -Procedure in sage::lir - Rust +Procedure in sage::lir - Rust

Struct sage::lir::Procedure

source ·
pub struct Procedure { /* private fields */ }
Expand description

A monomorphic procedure of LIR code which can be applied to a list of arguments. A procedure is compiled down to a label in the assembly code. The label is called with the Call instruction.

@@ -24,8 +24,8 @@ env: &mut Env, output: &mut dyn AssemblyProgram ) -> Result<(), Error>

source§

fn compile(self) -> Result<Result<CoreProgram, StandardProgram>, Error>
where - Self: Sized + Clone,

Compile the expression into an assembly program. Read more
source§

impl Debug for Procedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Procedure

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Procedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl GetType for Procedure

source§

fn get_type_checked(&self, _env: &Env, _i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check + Self: Sized + Clone,
Compile the expression into an assembly program. Read more
source§

impl Debug for Procedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Procedure

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Procedure

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<Procedure> for ConstExpr

source§

fn from(value: Procedure) -> Self

Converts to this type from the input type.
source§

impl GetType for Procedure

source§

fn get_type_checked(&self, _env: &Env, _i: usize) -> Result<Type, Error>

Get the type of a value under a given environment and check recursion depth to prevent a possible stack overflow.
source§

fn substitute(&mut self, name: &str, ty: &Type)

Substitute a type for a given name in the environment.
source§

fn get_type(&self, env: &Env) -> Result<Type, Error>

Get the type associated with a value under a given environment.
source§

fn substitute_types(&mut self, names: &[String], types: &[Type])

source§

impl Hash for Procedure

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl PartialEq for Procedure

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used @@ -34,9 +34,9 @@ __S: Serializer,
Serialize this value into the given Serde serializer. Read more
source§

impl TypeCheck for Procedure

source§

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.
source§

impl Eq for Procedure

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where - T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

-
source§

impl<T> GetSize for T
where - T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive + T: ?Sized,
source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T> GetSize for T
where + T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive calls to prevent stack overflow. i is a counter to prevent infinite recursion.
source§

fn get_size(&self, env: &Env) -> Result<usize, Error>

Get the size of something in memory (number of cells).
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

diff --git a/docs/sage/lir/struct.StandardBuiltin.html b/docs/sage/lir/struct.StandardBuiltin.html index 274242b9..a0cb61fe 100644 --- a/docs/sage/lir/struct.StandardBuiltin.html +++ b/docs/sage/lir/struct.StandardBuiltin.html @@ -30,8 +30,8 @@ T: 'static + ?Sized,
source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

-
source§

impl<T> GetSize for T
where - T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive +
source§

impl<T> GetSize for T
where + T: GetType,

source§

fn get_size_checked(&self, env: &Env, i: usize) -> Result<usize, Error>

Get the size of something in memory, but limit the number of recursive calls to prevent stack overflow. i is a counter to prevent infinite recursion.
source§

fn get_size(&self, env: &Env) -> Result<usize, Error>

Get the size of something in memory (number of cells).
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

diff --git a/docs/sage/lir/trait.AssignOp.html b/docs/sage/lir/trait.AssignOp.html index 6d60f040..7de97696 100644 --- a/docs/sage/lir/trait.AssignOp.html +++ b/docs/sage/lir/trait.AssignOp.html @@ -78,8 +78,8 @@ env: &mut Env, output: &mut dyn AssemblyProgram ) -> Result<(), Error>

Compiles the operation on the given expressions.

-

Trait Implementations§

source§

impl Clone for Box<dyn AssignOp>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Ord for dyn AssignOp

source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
source§

impl PartialEq for dyn AssignOp

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used +

Trait Implementations§

source§

impl Clone for Box<dyn AssignOp>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Ord for dyn AssignOp

source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
source§

impl PartialEq for dyn AssignOp

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for dyn AssignOp

source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for dyn AssignOp

source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
source§

impl Eq for dyn AssignOp

Implementors§

\ No newline at end of file +operator. Read more
source§

impl Eq for dyn AssignOp

Implementors§

\ No newline at end of file diff --git a/docs/sage/lir/trait.BinaryOp.html b/docs/sage/lir/trait.BinaryOp.html index 9753f5c5..f68ef12f 100644 --- a/docs/sage/lir/trait.BinaryOp.html +++ b/docs/sage/lir/trait.BinaryOp.html @@ -1,5 +1,5 @@ BinaryOp in sage::lir - Rust -

Trait sage::lir::BinaryOp

source ·
pub trait BinaryOp: Debug + Display + Send + Sync {
+    

Trait sage::lir::BinaryOp

source ·
pub trait BinaryOp: Debug + Display + Send + Sync {
     // Required methods
     fn clone_box(&self) -> Box<dyn BinaryOp>;
     fn can_apply(
@@ -55,7 +55,7 @@
     rhs: &ConstExpr,
     env: &mut Env
 ) -> Result<ConstExpr, Error>

Evaluates the operation on the given constant expressions.

-
source

fn compile_types( +

source

fn compile_types( &self, lhs: &Type, rhs: &Type, @@ -78,8 +78,8 @@ env: &mut Env, output: &mut dyn AssemblyProgram ) -> Result<(), Error>

Compiles the operation on the given expressions.

-

Trait Implementations§

source§

impl Clone for Box<dyn BinaryOp>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Ord for dyn BinaryOp

source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
source§

impl PartialEq for dyn BinaryOp

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used +

Trait Implementations§

source§

impl Clone for Box<dyn BinaryOp>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Ord for dyn BinaryOp

source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
source§

impl PartialEq for dyn BinaryOp

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for dyn BinaryOp

source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for dyn BinaryOp

source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
source§

impl Eq for dyn BinaryOp

Implementors§

\ No newline at end of file +operator. Read more
source§

impl Eq for dyn BinaryOp

Implementors§

\ No newline at end of file diff --git a/docs/sage/lir/trait.Compile.html b/docs/sage/lir/trait.Compile.html index 17bf8372..55aa27ff 100644 --- a/docs/sage/lir/trait.Compile.html +++ b/docs/sage/lir/trait.Compile.html @@ -21,6 +21,6 @@

On success, this will return an Ok value containing either a successfully compiled core assembly program, or a fallback standard assembly program.

On an error, this will return an Err value containing the error.

-

Implementors§

source§

impl Compile for ConstExpr

Compile a constant expression.

+

Implementors§

source§

impl Compile for ConstExpr

Compile a constant expression.

source§

impl Compile for Expr

Compile an LIR expression into several core assembly instructions.

source§

impl Compile for CoreBuiltin

source§

impl Compile for FFIProcedure

source§

impl Compile for Procedure

source§

impl Compile for StandardBuiltin

\ No newline at end of file diff --git a/docs/sage/lir/trait.GetSize.html b/docs/sage/lir/trait.GetSize.html index ad7afd67..33975fb7 100644 --- a/docs/sage/lir/trait.GetSize.html +++ b/docs/sage/lir/trait.GetSize.html @@ -10,8 +10,8 @@ calls to prevent stack overflow. i is a counter to prevent infinite recursion.

Provided Methods§

source

fn get_size(&self, env: &Env) -> Result<usize, Error>

Get the size of something in memory (number of cells).

-

Implementors§

source§

impl GetSize for Type

Calculate the size of a type in units of cells.

-
source§

impl<T> GetSize for T
where +

Implementors§

source§

impl GetSize for Type

Calculate the size of a type in units of cells.

+
source§

impl<T> GetSize for T
where T: GetType,

Implement GetSize for any type that implements GetType.

We can do this because the size of a variable should be exactly the size of its type.

diff --git a/docs/sage/lir/trait.GetType.html b/docs/sage/lir/trait.GetType.html index b2250a74..8ad76089 100644 --- a/docs/sage/lir/trait.GetType.html +++ b/docs/sage/lir/trait.GetType.html @@ -12,5 +12,5 @@ recursion depth to prevent a possible stack overflow.

source

fn substitute(&mut self, name: &str, ty: &Type)

Substitute a type for a given name in the environment.

Provided Methods§

source

fn get_type(&self, env: &Env) -> Result<Type, Error>

Get the type associated with a value under a given environment.

-
source

fn substitute_types(&mut self, names: &[String], types: &[Type])

Implementors§

source§

impl GetType for ConstExpr

source§

impl GetType for Expr

Infer the type associated with an expression under a given environment.

-
source§

impl GetType for CoreBuiltin

source§

impl GetType for FFIProcedure

source§

impl GetType for PolyProcedure

source§

impl GetType for Procedure

source§

impl GetType for StandardBuiltin

\ No newline at end of file +
source

fn substitute_types(&mut self, names: &[String], types: &[Type])

Implementors§

source§

impl GetType for ConstExpr

source§

impl GetType for Expr

Infer the type associated with an expression under a given environment.

+
source§

impl GetType for CoreBuiltin

source§

impl GetType for FFIProcedure

source§

impl GetType for PolyProcedure

source§

impl GetType for Procedure

source§

impl GetType for StandardBuiltin

\ No newline at end of file diff --git a/docs/sage/lir/trait.Simplify.html b/docs/sage/lir/trait.Simplify.html index 272b628a..7b6bf0e7 100644 --- a/docs/sage/lir/trait.Simplify.html +++ b/docs/sage/lir/trait.Simplify.html @@ -10,4 +10,4 @@ the number of recursive calls to prevent stack overflow. i is a counter to prevent infinite recursion.

Provided Methods§

source

fn simplify(self, env: &Env) -> Result<Self, Error>

Simplify an expression while maintaining structural equality.

-

Object Safety§

This trait is not object safe.

Implementors§

\ No newline at end of file +

Object Safety§

This trait is not object safe.

Implementors§

\ No newline at end of file diff --git a/docs/sage/lir/trait.TernaryOp.html b/docs/sage/lir/trait.TernaryOp.html index 83a15e91..5198065e 100644 --- a/docs/sage/lir/trait.TernaryOp.html +++ b/docs/sage/lir/trait.TernaryOp.html @@ -1,5 +1,5 @@ TernaryOp in sage::lir - Rust -

Trait sage::lir::TernaryOp

source ·
pub trait TernaryOp: Debug + Display + Send + Sync {
+    

Trait sage::lir::TernaryOp

source ·
pub trait TernaryOp: Debug + Display + Send + Sync {
     // Required methods
     fn clone_box(&self) -> Box<dyn TernaryOp>;
     fn can_apply(
@@ -58,22 +58,22 @@
         output: &mut dyn AssemblyProgram
     ) -> Result<(), Error> { ... }
 }
Expand description

A trait used to implement a ternary operation.

-

Required Methods§

source

fn clone_box(&self) -> Box<dyn TernaryOp>

Clones the operation into a boxed trait object.

-
source

fn can_apply( +

Required Methods§

source

fn clone_box(&self) -> Box<dyn TernaryOp>

Clones the operation into a boxed trait object.

+
source

fn can_apply( &self, a: &Type, b: &Type, c: &Type, env: &Env ) -> Result<bool, Error>

Checks if the operation can be applied to the given types.

-
source

fn eval( +

source

fn eval( &self, a: &ConstExpr, b: &ConstExpr, c: &ConstExpr, env: &mut Env ) -> Result<ConstExpr, Error>

Evaluates the operation on the given constant expressions.

-
source

fn compile_types( +

source

fn compile_types( &self, a: &Type, b: &Type, @@ -81,29 +81,29 @@ env: &mut Env, output: &mut dyn AssemblyProgram ) -> Result<(), Error>

Compiles the operation on the given types. (Generates the code for the operation.)

-

Provided Methods§

Provided Methods§

source

fn name(&self) -> String

source

fn type_check( &self, a: &Expr, b: &Expr, c: &Expr, env: &Env ) -> Result<(), Error>

Typechecks the operation on the given expressions.

-
source

fn return_type( +

source

fn return_type( &self, a: &Expr, b: &Expr, c: &Expr, env: &Env ) -> Result<Type, Error>

Gets the type of the operation on the given expressions.

-
source

fn display(&self, a: &Expr, b: &Expr, c: &Expr) -> String

Formats the operation for display.

-
source

fn can_apply_exprs( +

source

fn display(&self, a: &Expr, b: &Expr, c: &Expr) -> String

Formats the operation for display.

+
source

fn can_apply_exprs( &self, a: &Expr, b: &Expr, c: &Expr, env: &Env ) -> Result<bool, Error>

Checks if the operation can be applied to the given expressions.

-
source

fn compile( +

source

fn compile( &self, a: &Expr, b: &Expr, @@ -111,8 +111,8 @@ env: &mut Env, output: &mut dyn AssemblyProgram ) -> Result<(), Error>

Compiles the operation on the given expressions.

-

Trait Implementations§

source§

impl Clone for Box<dyn TernaryOp>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Ord for dyn TernaryOp

source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
source§

impl PartialEq for dyn TernaryOp

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used +

Trait Implementations§

source§

impl Clone for Box<dyn TernaryOp>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Ord for dyn TernaryOp

source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
source§

impl PartialEq for dyn TernaryOp

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for dyn TernaryOp

source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for dyn TernaryOp

source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
source§

impl Eq for dyn TernaryOp

Implementors§

\ No newline at end of file +operator. Read more
source§

impl Eq for dyn TernaryOp

Implementors§

\ No newline at end of file diff --git a/docs/sage/lir/trait.TypeCheck.html b/docs/sage/lir/trait.TypeCheck.html index 714565ee..0d1ce66b 100644 --- a/docs/sage/lir/trait.TypeCheck.html +++ b/docs/sage/lir/trait.TypeCheck.html @@ -6,6 +6,6 @@

Whenever this is applied, it will return Ok(()) if the typing is sound, and Err(...) if it is not.

Required Methods§

source

fn type_check(&self, env: &Env) -> Result<(), Error>

Type check the expression.

-

Implementors§

source§

impl TypeCheck for ConstExpr

source§

impl TypeCheck for Declaration

source§

impl TypeCheck for Expr

Check the type-soundness of a given expression.

-
source§

impl TypeCheck for Type

Check the soundness of a given type in the environment.

-
source§

impl TypeCheck for CoreBuiltin

source§

impl TypeCheck for FFIProcedure

source§

impl TypeCheck for PolyProcedure

source§

impl TypeCheck for Procedure

source§

impl TypeCheck for StandardBuiltin

\ No newline at end of file +

Implementors§

source§

impl TypeCheck for ConstExpr

source§

impl TypeCheck for Declaration

source§

impl TypeCheck for Expr

Check the type-soundness of a given expression.

+
source§

impl TypeCheck for Type

Check the soundness of a given type in the environment.

+
source§

impl TypeCheck for CoreBuiltin

source§

impl TypeCheck for FFIProcedure

source§

impl TypeCheck for PolyProcedure

source§

impl TypeCheck for Procedure

source§

impl TypeCheck for StandardBuiltin

\ No newline at end of file diff --git a/docs/sage/lir/trait.UnaryOp.html b/docs/sage/lir/trait.UnaryOp.html index a13d019f..02e5bf70 100644 --- a/docs/sage/lir/trait.UnaryOp.html +++ b/docs/sage/lir/trait.UnaryOp.html @@ -44,8 +44,8 @@ env: &mut Env, output: &mut dyn AssemblyProgram ) -> Result<(), Error>

Compiles the operation on the given expression.

-

Trait Implementations§

source§

impl Clone for Box<dyn UnaryOp>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Ord for dyn UnaryOp

source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
source§

impl PartialEq for dyn UnaryOp

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used +

Trait Implementations§

source§

impl Clone for Box<dyn UnaryOp>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Ord for dyn UnaryOp

source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
source§

impl PartialEq for dyn UnaryOp

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for dyn UnaryOp

source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for dyn UnaryOp

source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
source§

impl Eq for dyn UnaryOp

Implementors§

\ No newline at end of file +operator. Read more
source§

impl Eq for dyn UnaryOp

Implementors§

\ No newline at end of file diff --git a/docs/sage/side_effects/io/enum.Axis.html b/docs/sage/side_effects/io/enum.Axis.html index 5b91d32f..3cf24ab1 100644 --- a/docs/sage/side_effects/io/enum.Axis.html +++ b/docs/sage/side_effects/io/enum.Axis.html @@ -4,8 +4,8 @@ Y, Z, }
Expand description

The different axes an input or output might use.

-

Variants§

Trait Implementations§

source§

impl Clone for Axis

source§

fn clone(&self) -> Axis

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Axis

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Axis

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Axis

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Axis

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Variants§

Trait Implementations§

source§

impl Clone for Axis

source§

fn clone(&self) -> Axis

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Axis

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Axis

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Axis

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Axis

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for Axis

source§

fn cmp(&self, other: &Axis) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/side_effects/io/enum.Direction.html b/docs/sage/side_effects/io/enum.Direction.html index 97d1e600..820e0d16 100644 --- a/docs/sage/side_effects/io/enum.Direction.html +++ b/docs/sage/side_effects/io/enum.Direction.html @@ -5,8 +5,8 @@ Left, Right, }
Expand description

The different directions a D-Pad a might use.

-

Variants§

§

Up

§

Down

§

Left

§

Right

Trait Implementations§

source§

impl Clone for Direction

source§

fn clone(&self) -> Direction

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Direction

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Direction

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Direction

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Direction

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Variants§

§

Up

§

Down

§

Left

§

Right

Trait Implementations§

source§

impl Clone for Direction

source§

fn clone(&self) -> Direction

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Direction

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Direction

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Direction

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Direction

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for Direction

source§

fn cmp(&self, other: &Direction) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/side_effects/io/struct.Channel.html b/docs/sage/side_effects/io/struct.Channel.html index f08678e6..e4dee3a0 100644 --- a/docs/sage/side_effects/io/struct.Channel.html +++ b/docs/sage/side_effects/io/struct.Channel.html @@ -1,7 +1,7 @@ Channel in sage::side_effects::io - Rust

Struct sage::side_effects::io::Channel

source ·
pub struct Channel(pub usize);
Expand description

The channel to use for a given I/O mode.

-

Tuple Fields§

§0: usize

Trait Implementations§

source§

impl Clone for Channel

source§

fn clone(&self) -> Channel

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Channel

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Channel

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Channel

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Channel

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Tuple Fields§

§0: usize

Trait Implementations§

source§

impl Clone for Channel

source§

fn clone(&self) -> Channel

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Channel

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Channel

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Channel

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Channel

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for Channel

source§

fn cmp(&self, other: &Channel) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/side_effects/io/struct.Input.html b/docs/sage/side_effects/io/struct.Input.html index 0fe32012..305e5251 100644 --- a/docs/sage/side_effects/io/struct.Input.html +++ b/docs/sage/side_effects/io/struct.Input.html @@ -11,8 +11,8 @@

source

pub const fn stdin_float() -> Self

Input from STDIN (float)

source

pub const fn random() -> Self

A random number

source

pub const fn clock() -> Self

The time (in seconds) since the program started

-

Trait Implementations§

source§

impl Clone for Input

source§

fn clone(&self) -> Input

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Input

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Input

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where - __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Input

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Input

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Trait Implementations§

source§

impl Clone for Input

source§

fn clone(&self) -> Input

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Input

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Input

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where + __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for Input

source§

fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult

Formats the value using the given formatter. Read more
source§

impl Hash for Input

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for Input

source§

fn cmp(&self, other: &Input) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/vm/enum.CoreOp.html b/docs/sage/vm/enum.CoreOp.html index 664d8fdc..27167e2e 100644 --- a/docs/sage/vm/enum.CoreOp.html +++ b/docs/sage/vm/enum.CoreOp.html @@ -117,7 +117,7 @@ The argument is the size of the vector to check if the register is non-negative.

§

Get(Input)

Get a value from an input source and store it in the register.

§

Put(Output)

Write the value of the register to an output source.

-

Trait Implementations§

source§

impl Clone for CoreOp

source§

fn clone(&self) -> CoreOp

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for CoreOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for CoreOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Hash for CoreOp

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Trait Implementations§

source§

impl Clone for CoreOp

source§

fn clone(&self) -> CoreOp

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for CoreOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for CoreOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Hash for CoreOp

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for CoreOp

source§

fn cmp(&self, other: &CoreOp) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/vm/enum.StandardOp.html b/docs/sage/vm/enum.StandardOp.html index 39622c8f..8a4250f0 100644 --- a/docs/sage/vm/enum.StandardOp.html +++ b/docs/sage/vm/enum.StandardOp.html @@ -1,5 +1,5 @@ StandardOp in sage::vm - Rust -

Enum sage::vm::StandardOp

source ·
pub enum StandardOp {
+    

Enum sage::vm::StandardOp

source ·
pub enum StandardOp {
 
Show 23 variants CoreOp(CoreOp), Set(Vec<f64>), Alloc, @@ -61,11 +61,11 @@ FFI buffer of cells. Whenever an FFI function is called, it will receive its arguments from this buffer.

§

Call(FFIBinding)

Call a foreign function interface function.

-

Trait Implementations§

source§

impl Clone for StandardOp

source§

fn clone(&self) -> StandardOp

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for StandardOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for StandardOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for StandardOp

source§

fn eq(&self, other: &StandardOp) -> bool

This method tests for self and other values to be equal, and is used +

Trait Implementations§

source§

impl Clone for StandardOp

source§

fn clone(&self) -> StandardOp

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for StandardOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for StandardOp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for StandardOp

source§

fn eq(&self, other: &StandardOp) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for StandardOp

source§

fn partial_cmp(&self, other: &StandardOp) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for StandardOp

source§

fn partial_cmp(&self, other: &StandardOp) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
source§

impl StructuralPartialEq for StandardOp

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where +operator. Read more

source§

impl StructuralPartialEq for StandardOp

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/docs/sage/vm/struct.CoreProgram.html b/docs/sage/vm/struct.CoreProgram.html index 6d1f8a2d..7bb7c885 100644 --- a/docs/sage/vm/struct.CoreProgram.html +++ b/docs/sage/vm/struct.CoreProgram.html @@ -5,7 +5,7 @@
source

pub fn get_main(&self) -> Vec<CoreOp>

Get the code outside of any functions.

source

pub fn get_functions(&self) -> HashMap<i32, Vec<CoreOp>>

Get the code for each function.

source

pub fn get_main_and_functions(self) -> (Vec<CoreOp>, HashMap<i32, Vec<CoreOp>>)

Get the code outside of any functions, and the code for each function.

-

Trait Implementations§

source§

impl Clone for CoreProgram

source§

fn clone(&self) -> CoreProgram

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Default for CoreProgram

source§

fn default() -> CoreProgram

Returns the “default value” for a type. Read more
source§

impl Display for CoreProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<CoreProgram> for StandardProgram

source§

fn from(core: CoreProgram) -> Self

Converts to this type from the input type.
source§

impl Hash for CoreProgram

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where +

Trait Implementations§

source§

impl Clone for CoreProgram

source§

fn clone(&self) -> CoreProgram

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Default for CoreProgram

source§

fn default() -> CoreProgram

Returns the “default value” for a type. Read more
source§

impl Display for CoreProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<CoreProgram> for StandardProgram

source§

fn from(core: CoreProgram) -> Self

Converts to this type from the input type.
source§

impl Hash for CoreProgram

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for CoreProgram

source§

fn cmp(&self, other: &CoreProgram) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where diff --git a/docs/sage/vm/struct.StandardProgram.html b/docs/sage/vm/struct.StandardProgram.html index f677fd1d..037cdb19 100644 --- a/docs/sage/vm/struct.StandardProgram.html +++ b/docs/sage/vm/struct.StandardProgram.html @@ -1,17 +1,17 @@ StandardProgram in sage::vm - Rust -

Struct sage::vm::StandardProgram

source ·
pub struct StandardProgram(pub Vec<StandardOp>);
Expand description

A program of core and standard virtual machine instructions.

-

Tuple Fields§

§0: Vec<StandardOp>

Implementations§

source§

impl StandardProgram

source

pub fn flatten(self) -> Self

Flatten a core program so that all of its functions +

Struct sage::vm::StandardProgram

source ·
pub struct StandardProgram(pub Vec<StandardOp>);
Expand description

A program of core and standard virtual machine instructions.

+

Tuple Fields§

§0: Vec<StandardOp>

Implementations§

source§

impl StandardProgram

source

pub fn flatten(self) -> Self

Flatten a core program so that all of its functions are defined sequentially at the beginning.

-
source

pub fn get_main(&self) -> Vec<StandardOp>

Get the code outside of any functions.

-
source

pub fn get_functions(&self) -> HashMap<i32, Vec<StandardOp>>

Get the code for each function.

-
source

pub fn get_main_and_functions( +

source

pub fn get_main(&self) -> Vec<StandardOp>

Get the code outside of any functions.

+
source

pub fn get_functions(&self) -> HashMap<i32, Vec<StandardOp>>

Get the code for each function.

+
source

pub fn get_main_and_functions( self ) -> (Vec<StandardOp>, HashMap<i32, Vec<StandardOp>>)

Get the code outside of any functions, and the code for each function.

-

Trait Implementations§

source§

impl Clone for StandardProgram

source§

fn clone(&self) -> StandardProgram

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Default for StandardProgram

source§

fn default() -> StandardProgram

Returns the “default value” for a type. Read more
source§

impl Display for StandardProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<CoreProgram> for StandardProgram

source§

fn from(core: CoreProgram) -> Self

Converts to this type from the input type.
source§

impl PartialEq for StandardProgram

source§

fn eq(&self, other: &StandardProgram) -> bool

This method tests for self and other values to be equal, and is used +

Trait Implementations§

source§

impl Clone for StandardProgram

source§

fn clone(&self) -> StandardProgram

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Default for StandardProgram

source§

fn default() -> StandardProgram

Returns the “default value” for a type. Read more
source§

impl Display for StandardProgram

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<CoreProgram> for StandardProgram

source§

fn from(core: CoreProgram) -> Self

Converts to this type from the input type.
source§

impl PartialEq for StandardProgram

source§

fn eq(&self, other: &StandardProgram) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for StandardProgram

source§

fn partial_cmp(&self, other: &StandardProgram) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for StandardProgram

source§

fn partial_cmp(&self, other: &StandardProgram) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
source§

impl VirtualMachineProgram for StandardProgram

source§

fn op(&mut self, op: CoreOp)

source§

fn std_op(&mut self, op: StandardOp) -> Result<(), Error>

source§

fn code(&self) -> Result<CoreProgram, StandardProgram>

source§

fn set_float_vector(&mut self, vector: Vec<f64>) -> Result<(), Error>

source§

fn set_vector(&mut self, vector: Vec<i64>)

source§

fn store_vector(&mut self, n: usize)

source§

fn load_vector(&mut self, n: usize)

source§

fn ffi_call(&mut self, ffi: FFIBinding) -> Result<(), Error>

source§

fn poke(&mut self) -> Result<(), Error>

source§

fn peek(&mut self) -> Result<(), Error>

source§

fn comment(&mut self, comment: &str)

source§

fn restore(&mut self)

source§

fn save(&mut self)

source§

fn ret(&mut self)

source§

fn where_is_pointer(&mut self)

source§

fn deref(&mut self)

source§

fn refer(&mut self)

source§

fn move_pointer(&mut self, cells: isize)

source§

fn set_register(&mut self, val: i64)

source§

fn set_float_register(&mut self, val: f64) -> Result<(), Error>

source§

fn begin_while(&mut self)

source§

fn begin_if(&mut self)

source§

fn begin_else(&mut self)

source§

fn begin_function(&mut self)

source§

fn end(&mut self)

source§

fn call(&mut self)

source§

fn index(&mut self)

source§

fn bitwise_nand(&mut self)

source§

fn get(&mut self, src: Input)

source§

fn put(&mut self, dst: Output)

source§

fn is_non_negative(&mut self)

source§

impl StructuralPartialEq for StandardProgram

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where +operator. Read more

source§

impl VirtualMachineProgram for StandardProgram

source§

fn op(&mut self, op: CoreOp)

source§

fn std_op(&mut self, op: StandardOp) -> Result<(), Error>

source§

fn code(&self) -> Result<CoreProgram, StandardProgram>

source§

fn set_float_vector(&mut self, vector: Vec<f64>) -> Result<(), Error>

source§

fn set_vector(&mut self, vector: Vec<i64>)

source§

fn store_vector(&mut self, n: usize)

source§

fn load_vector(&mut self, n: usize)

source§

fn ffi_call(&mut self, ffi: FFIBinding) -> Result<(), Error>

source§

fn poke(&mut self) -> Result<(), Error>

source§

fn peek(&mut self) -> Result<(), Error>

source§

fn comment(&mut self, comment: &str)

source§

fn restore(&mut self)

source§

fn save(&mut self)

source§

fn ret(&mut self)

source§

fn where_is_pointer(&mut self)

source§

fn deref(&mut self)

source§

fn refer(&mut self)

source§

fn move_pointer(&mut self, cells: isize)

source§

fn set_register(&mut self, val: i64)

source§

fn set_float_register(&mut self, val: f64) -> Result<(), Error>

source§

fn begin_while(&mut self)

source§

fn begin_if(&mut self)

source§

fn begin_else(&mut self)

source§

fn begin_function(&mut self)

source§

fn end(&mut self)

source§

fn call(&mut self)

source§

fn index(&mut self)

source§

fn bitwise_nand(&mut self)

source§

fn get(&mut self, src: Input)

source§

fn put(&mut self, dst: Output)

source§

fn is_non_negative(&mut self)

source§

impl StructuralPartialEq for StandardProgram

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

diff --git a/docs/sage/vm/trait.VirtualMachineProgram.html b/docs/sage/vm/trait.VirtualMachineProgram.html index 94d503bb..bd0fe2f4 100644 --- a/docs/sage/vm/trait.VirtualMachineProgram.html +++ b/docs/sage/vm/trait.VirtualMachineProgram.html @@ -36,4 +36,4 @@ fn is_non_negative(&mut self) { ... }
}
Expand description

An interface to conveniently create virtual machine programs, of either the core or standard variant.

-

Required Methods§

source

fn op(&mut self, op: CoreOp)

source

fn std_op(&mut self, op: StandardOp) -> Result<(), Error>

source

fn code(&self) -> Result<CoreProgram, StandardProgram>

Provided Methods§

source

fn set_float_vector(&mut self, vector: Vec<f64>) -> Result<(), Error>

source

fn set_vector(&mut self, vector: Vec<i64>)

source

fn store_vector(&mut self, n: usize)

source

fn load_vector(&mut self, n: usize)

source

fn ffi_call(&mut self, ffi: FFIBinding) -> Result<(), Error>

source

fn poke(&mut self) -> Result<(), Error>

source

fn peek(&mut self) -> Result<(), Error>

source

fn comment(&mut self, comment: &str)

source

fn restore(&mut self)

source

fn save(&mut self)

source

fn ret(&mut self)

source

fn where_is_pointer(&mut self)

source

fn deref(&mut self)

source

fn refer(&mut self)

source

fn move_pointer(&mut self, cells: isize)

source

fn set_register(&mut self, val: i64)

source

fn set_float_register(&mut self, val: f64) -> Result<(), Error>

source

fn begin_while(&mut self)

source

fn begin_if(&mut self)

source

fn begin_else(&mut self)

source

fn begin_function(&mut self)

source

fn end(&mut self)

source

fn call(&mut self)

source

fn index(&mut self)

source

fn bitwise_nand(&mut self)

source

fn get(&mut self, src: Input)

source

fn put(&mut self, dst: Output)

source

fn is_non_negative(&mut self)

Implementors§

\ No newline at end of file +

Required Methods§

source

fn op(&mut self, op: CoreOp)

source

fn std_op(&mut self, op: StandardOp) -> Result<(), Error>

source

fn code(&self) -> Result<CoreProgram, StandardProgram>

Provided Methods§

source

fn set_float_vector(&mut self, vector: Vec<f64>) -> Result<(), Error>

source

fn set_vector(&mut self, vector: Vec<i64>)

source

fn store_vector(&mut self, n: usize)

source

fn load_vector(&mut self, n: usize)

source

fn ffi_call(&mut self, ffi: FFIBinding) -> Result<(), Error>

source

fn poke(&mut self) -> Result<(), Error>

source

fn peek(&mut self) -> Result<(), Error>

source

fn comment(&mut self, comment: &str)

source

fn restore(&mut self)

source

fn save(&mut self)

source

fn ret(&mut self)

source

fn where_is_pointer(&mut self)

source

fn deref(&mut self)

source

fn refer(&mut self)

source

fn move_pointer(&mut self, cells: isize)

source

fn set_register(&mut self, val: i64)

source

fn set_float_register(&mut self, val: f64) -> Result<(), Error>

source

fn begin_while(&mut self)

source

fn begin_if(&mut self)

source

fn begin_else(&mut self)

source

fn begin_function(&mut self)

source

fn end(&mut self)

source

fn call(&mut self)

source

fn index(&mut self)

source

fn bitwise_nand(&mut self)

source

fn get(&mut self, src: Input)

source

fn put(&mut self, dst: Output)

source

fn is_non_negative(&mut self)

Implementors§

\ No newline at end of file diff --git a/docs/sage/web/index.html b/docs/sage/web/index.html index eb344948..de6ab312 100644 --- a/docs/sage/web/index.html +++ b/docs/sage/web/index.html @@ -85,6 +85,138 @@ } console.log(document.getElementById("example").value); switch (document.getElementById("example").value) { + case "const-generics": + source.setValue(`fun main() { + // Create an array struct + let mut a = Array.new([1, 2, 3, 4, 5]); + // Print it out + a.println(); + // Set a value! + a.set(1, 1000); + // Print the changed value + println(*a.get(1)); + // Print the whole changed array + a.println(); +} + +// An array with a constant parameter length +struct Array { + data: [T * N] +} + +impl Array { + // Create a new Array container + fun new(arr: [T * N]): Array { + return {data=arr}; + } + + // Get a value from the array + fun get(&self, n: Int): &T { + if n < N { + return &self.data[n]; + } else { + return Null; + } + } + + // Set a value in the array + fun set(&mut self, n: Int, val: T) { + self.data[n] = val; + } + + // Print the array + fun print(&self) { + print("["); + for let mut i=0; i(10); // Populate with 10 + let y = Matrix.new(5); // Populate with 5 + + // Print the two matrices + x.print(); + y.print(); + + // Provide the matrix with the operations for the elem type + fun add_ints(a: Int, b: Int): Int = a + b; + fun mul_ints(a: Int, b: Int): Int = a * b; + + // Perform the mat mul! + let z = y.mul<4>(&x, 0, add_ints, mul_ints); + // Print the result + z.print(); +} + +// Define a constant sized matrix with a generic element type +// and parameterized width and height. +struct Matrix { + arr: [[T * Cols] * Rows] +} + +// Add some methods to our matrix +impl Matrix { + // Create a new matrix populated with initial values + fun new(x: T): Matrix { + return {arr=[[x] * Cols] * Rows}; + } + + // Get a value from a matrix + fun get(&self, row: Int, col: Int): &T { + return &self.arr[row][col]; + } + + // Multiply with another matrix + fun mul( + &self, + other: &Matrix, + zero: T, + add: fun(T, T) -> T, + mul: fun(T, T) -> T + ): Matrix { + let mut result = Matrix.new(zero); + for let mut j=0; j { + source.setValue(`fun main() { + let x = Option of Some(5); + println(x.unwrap()); +} + +enum Option { Some(T), Nothing, } @@ -1830,11 +1967,6 @@ } } -fun main() { - let x = Option of Some(5); - println(Option.unwrap(x)); -} - main();`) break; default: @@ -1899,7 +2031,9 @@ + + diff --git a/docs/sage/web/web_bg.wasm b/docs/sage/web/web_bg.wasm index 0281e6fd..208c8a20 100644 Binary files a/docs/sage/web/web_bg.wasm and b/docs/sage/web/web_bg.wasm differ diff --git a/docs/search-index.js b/docs/search-index.js index f860946d..e5781a4e 100644 --- a/docs/search-index.js +++ b/docs/search-index.js @@ -1,5 +1,5 @@ var searchIndex = new Map(JSON.parse('[\ -["sage",{"doc":"The Sage Programming Language","t":"SSSCCCCCCCEKEEEEEEGEEEEEEEEEPPPPPPNNNNNCMNNNNNNNNMCNNMCNMNCMNNNNNPPPPPPPPPPPPPPPPGFPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPNNNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOFNNNNNNNNNNNNNNNNNNNNNNNNNNNSPSSSSSSSPPGPSSNNNNNNNNNNNNNNNNNNNNNNNNNPPPPPPPPPPPPPPPPPPPPPGFPPPPPPPPPPPPPPPPPPPNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOHFPPFPPPGPPPPPPGPPPPPPFKPKPFFFFFFPPTTPPPPGKPPPGPPPFPPTFPPGPPFPPPPPPPPPPFPGGPFPPPPPFKKPPPPPPPPPPPPPPPPPPPPPPPPPPTPPPPPPPPPPPPPPPPGPTFPPFPPPPPPFPPPFGPPPPPFPPPPFGPPPPPTKPPPFPPPPPPPPPPPTFPPKPPPPPGPPPKPPPTKPPPPPPPPPPPPPPPPNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOOOOOFNNNNNONNNNNONNNNNNOOOHHHHHNNNNNNCCFNNNNNNNNNNNNNNNONONONNNNNNNPPPPGPPPPPPPPPPFPPGPPPPPPPPPPGPPPPPPPPFGPPPPPPPPPPPPPPFGPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNKKNNNNCMMMNMMMMNNNNNMMMMMMFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNPPPPPPPPPPPPPPPPFGPFPPPKPPPPGPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPFFGFPPPPPFPPPKPPNHHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOMNNNONNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNMNNONNNNNNNMNNNMNNNMNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","n":["LOGO","LOGO_WITH_COLOR","NULL","asm","frontend","lir","parse","side_effects","targets","vm","A","AssemblyProgram","B","C","CoreOp","CoreProgram","D","E","Error","F","FP","GP","Globals","Location","REGISTERS","SP","StandardOp","StandardProgram","UndefinedGlobal","UndefinedLabel","Unexpected","Unmatched","UnsupportedInstruction","VirtualMachineError","borrow","borrow_mut","clone","clone_into","comment","core","current_instruction","deref","deref_mut","drop","eq","fmt","fmt","from","from","get_op","globals","init","into","is_defined","location","log_instructions_after","op","partial_cmp","std","std_op","to_owned","to_string","try_from","try_into","type_id","Add","And","ArithmeticRightShift","Array","BitwiseAnd","BitwiseNand","BitwiseNor","BitwiseNot","BitwiseOr","BitwiseXor","Call","CallLabel","Comment","Compare","Const","Copy","CoreOp","CoreProgram","Dec","Div","DivRem","Else","End","Fn","Get","GetAddress","Global","If","Inc","Index","IsEqual","IsGreater","IsGreaterEqual","IsLess","IsLessEqual","IsNotEqual","LeftShift","LogicalRightShift","Many","Move","Mul","Neg","Next","Not","Or","Pop","PopFrom","Prev","Push","PushAddress","PushConst","PushTo","Put","Rem","Return","Set","SetLabel","Sub","Swap","VecAdd","VecAnd","VecArithmeticRightShift","VecBitwiseAnd","VecBitwiseNand","VecBitwiseNor","VecBitwiseNot","VecBitwiseOr","VecBitwiseXor","VecDec","VecDiv","VecGez","VecInc","VecIndex","VecLeftShift","VecLogicalRightShift","VecMul","VecNeg","VecNot","VecOffset","VecOr","VecRem","VecSet","VecSub","While","assemble","borrow","borrow","borrow_mut","borrow_mut","clone","clone","clone_into","clone_into","cmp","cmp","code","current_instruction","default","deref","deref","deref_mut","deref_mut","deserialize","deserialize","drop","drop","eq","eq","fmt","fmt","fmt","fmt","from","from","get_op","hash","hash","init","init","into","into","is_defined","new","op","partial_cmp","partial_cmp","push_string","put_string","serialize","serialize","stack_alloc_string","std_op","to_owned","to_owned","to_string","to_string","try_from","try_from","try_into","try_into","type_id","type_id","a","a","a","a","a","a","a","addr","b","b","b","b","b","b","b","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","name","offset","offset","offset","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","sp","sp","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","vals","vals","Globals","add_global","borrow","borrow_mut","clone","clone_into","default","deref","deref_mut","deserialize","drop","fmt","fmt","from","get_global","get_global_location","get_global_size","get_size","init","into","new","resolve","serialize","to_owned","to_string","try_from","try_into","type_id","A","Address","B","C","D","E","F","FP","GP","Global","Indirect","Location","Offset","REGISTERS","SP","borrow","borrow_mut","clone","clone_into","cmp","deref","deref","deref_mut","deserialize","drop","eq","fmt","fmt","from","hash","init","into","offset","partial_cmp","serialize","to_owned","to_string","try_from","try_into","type_id","ACos","ASin","ATan","Add","Alloc","Call","Const","CoreOp","Cos","Div","Free","IsGreater","IsLess","Mul","Neg","Pow","PushConst","Rem","Set","Sin","Sqrt","StandardOp","StandardProgram","Sub","Tan","ToFloat","ToInt","VecACos","VecASin","VecATan","VecAdd","VecCos","VecDiv","VecGez","VecMul","VecNeg","VecPow","VecRem","VecSet","VecSin","VecSub","VecTan","assemble","borrow","borrow","borrow_mut","borrow_mut","clone","clone","clone_into","clone_into","code","current_instruction","default","deref","deref","deref_mut","deref_mut","deserialize","deserialize","drop","drop","eq","eq","fmt","fmt","fmt","fmt","from","from","from","get_op","init","init","into","into","is_defined","new","op","partial_cmp","partial_cmp","serialize","serialize","std_op","to_owned","to_owned","to_string","to_string","try_from","try_from","try_into","try_into","type_id","type_id","a","a","b","b","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","size","size","size","size","size","size","size","size","size","size","size","size","size","size","src","src","src","src","src","src","src","src","src","src","src","src","src","vals","parse","Add","Add","Alt","And","Annotated","Annotated","Annotated","Annotation","Any","Any","Apply","Apply","ApplyNonProc","ApplyNonTemplate","Arithmetic","Array","Array","Array","As","As","AssemblyError","Assign","AssignOp","AssignOp","BinaryOp","BinaryOp","BitwiseAnd","BitwiseNand","BitwiseNor","BitwiseNot","BitwiseOr","BitwiseXor","Bool","Bool","COMPILER_GENERATED","CONSTANT","Cell","Cell","Char","Char","Comparison","Compile","CompilePolyProc","CompilerGenerated","Const","ConstExpr","ConstExpr","ConstExpr","Constant","CoreBuiltin","CoreBuiltin","CouldntSimplify","DEAD_CODE","Data","DeadCode","Debug","Declaration","Declare","Declare","Delete","Deref","DerefMut","DerefNonPointer","Display","Divide","DuplicateMember","Enum","EnumUnion","EnumUnion","EnumUnion","Env","Equal","Error","Expr","ExternProc","FFIProcedure","FFIProcedure","Float","Float","FromImport","FromImportAll","Get","GetSize","GetType","GreaterThan","GreaterThanOrEqual","If","IfLet","Immutable","Impl","Index","Int","Int","InvalidAs","InvalidAssignOp","InvalidAssignOpTypes","InvalidBinaryOp","InvalidBinaryOpTypes","InvalidConstExpr","InvalidIndex","InvalidMatchExpr","InvalidMonomorphize","InvalidPatternForExpr","InvalidPatternForType","InvalidRefer","InvalidTemplateArgs","InvalidTernaryOp","InvalidTernaryOpTypes","InvalidUnaryOp","InvalidUnaryOpTypes","LIVE_CODE","LessThan","LessThanOrEqual","Let","Location","Many","Many","Many","Match","Member","Member","MemberNotFound","MismatchedMutability","MismatchedTypes","Module","Monomorphize","Multiply","Mutability","Mutable","NONE","Negate","NegativeArrayLength","Never","New","NonExhaustivePatterns","NonIntegralConst","NonSymbol","None","None","None","Not","NotEqual","Null","Of","Or","Pattern","Pointer","Pointer","Poly","PolyProc","PolyProc","PolyProcedure","Power","Proc","Proc","Proc","Procedure","Put","RecursionDepthConst","RecursionDepthTypeEquality","Refer","Remainder","Return","SIMPLIFY_RECURSION_LIMIT","Simplify","SizeOfExpr","SizeOfTemplate","SizeOfType","StandardBuiltin","StandardBuiltin","StaticVar","Struct","Struct","Struct","Struct","Subtract","Symbol","Symbol","Symbol","SymbolNotDefined","TEMPORARY","Tag","Template","Temporary","TernaryOp","TernaryOp","Tuple","Tuple","Tuple","Tuple","Type","Type","Type","Type","TypeCheck","TypeNotDefined","TypeOf","TypeRedefined","USER_GENERATED","UnaryOp","UnaryOp","UnimplementedOperator","Union","Union","Union","Unit","UnsizedType","UnsupportedOperation","UnusedExpr","Var","VarPat","Variant","VariantNotFound","When","While","Wildcard","add","add","add_assign","add_associated_const","add_monomorphized_associated_consts","alt","and","annotate","annotate","annotate","app","app","apply","are_patterns_exhaustive","args","args","as_bool","as_char","as_float","as_int","as_symbol","as_type","as_type","assign","assign_op","bitand","bitnand","bitnor","bitnot","bitor","bitor","bitor_assign","bitxor","body","body","bool","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_cast_to","can_decay_to","can_decay_to","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","compile","compile","compile","compile","compile","compile","compile","compile","compile","compile","compile","compile","compile_expr","compile_expr","compile_expr","compile_expr","compile_expr","compile_expr","compile_expr","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","contains_symbol","debug","declare_let_bind","default","default","define_types","define_var","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","display","display","display","display","display","display","display","display","display","div","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","equals","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","field","field","float","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_mono","ge","get_all_associated_consts","get_args","get_associated_const","get_bindings","get_body","get_branch_result_type","get_common_name","get_mangled_name","get_method_call_mutability","get_monomorph_template_args","get_name","get_ret","get_self_param_mutability","get_size","get_size","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_template_params","get_type","get_type","get_type_checked","get_type_checked","get_type_checked","get_type_checked","get_type_checked","get_type_checked","get_type_checked","get_type_checked","get_type_of_associated_const","gt","hard_with","has_associated_const","has_element_type","has_location","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","idx","if_let_pattern","if_then","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","int","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","is_atomic","is_compiler_generated","is_concrete","is_constant","is_dead_code","is_exhaustive","is_location","is_method_call","is_monomorph_of","is_mutable","is_none","is_poly","is_recursive","is_recursive_helper","is_self_param_reference","is_simple","is_temporary","le","let_bind","let_const","let_consts","let_proc","let_procs","let_type","let_types","let_var","let_vars","location","lt","many","match_pattern","module","monomorphize","monomorphize","mul","name","name","name","name","name","name","name","name","name","name","neg","neq","new","new","new","new","not","or","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","perform_template_applications","pointer","pow","print","println","proc","push_label","refer","rem","ret","ret","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","set_common_name","simplify","simplify_checked","simplify_checked","simplify_checked","simplify_until_atomic","simplify_until_concrete","simplify_until_has_members","simplify_until_has_variants","simplify_until_matches","simplify_until_poly","simplify_until_simple","simplify_until_type_checks","simplify_until_union","size_of","strip_template","struct_","structure","sub","substitute","substitute","substitute","substitute","substitute","substitute","substitute","substitute","substitute","substitute_types","substitute_types","sym","template","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","transform_method_call","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","tup","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unop","var","var","variant_index","while_loop","wildcard","with","with","with","with","module","names","expected","expected","expr","expr","expr","found","found","patterns","SourceCodeLocation","borrow","borrow_mut","clone","clone_into","cmp","column","deref","deref_mut","deserialize","drop","eq","filename","fmt","from","get_code","hash","init","into","length","line","offset","parse_asm","parse_frontend","parse_frontend_minimal","parse_lir","parse_vm","partial_cmp","serialize","to_owned","try_from","try_into","type_id","ffi","io","FFIBinding","borrow","borrow_mut","clone","clone_into","cmp","deref","deref_mut","deserialize","drop","eq","fmt","fmt","from","hash","init","input_cells","into","name","new","output_cells","partial_cmp","serialize","to_owned","to_string","try_from","try_into","type_id","Accelerometer","Altimeter","AnalogPin","AnalogPin","Axis","Barometer","Bell","Black","Blower","Blue","BlueLight","Brightness","Brightness","Button","Buzzer","Channel","ClearDisplay","Clock","Color","Compass","ConductivitySensor","Cooler","Custom","Custom","Cyan","DPad","DepthSensor","DigitalPin","DigitalPin","Direction","Down","Fan","FlowSensor","Green","GreenLight","Gyroscope","Heater","Humidity","Input","InputMode","JoyStick","Keyboard","Left","Magenta","Magnetometer","Microphone","MotorSpeed","MoveCursorDown","MoveCursorLeft","MoveCursorRight","MoveCursorUp","Note","Odometer","Orange","Output","OutputMode","PHSensor","Position","Pressure","PressureGauge","PrinterChar","PrinterFloat","PrinterInt","Proximity","Pump","RGB","RainGauge","Random","Red","RedLight","Right","Servo","SetCursorChar","SetCursorColumn","SetCursorPixel","SetCursorRow","Solenoid","SpeakerFrequency","SpeakerVolume","Speedometer","StderrChar","StderrFloat","StderrInt","StdinChar","StdinFloat","StdinInt","StdoutChar","StdoutFloat","StdoutInt","StepperMotor","Temperature","Thermometer","UVSensor","Up","UpdateDisplay","Valve","VolumeSensor","WeightSensor","White","WindDirection","WindSpeed","X","Y","Yellow","Z","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","channel","channel","clock","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","drop","drop","drop","drop","drop","drop","drop","drop","eq","eq","eq","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","hash","hash","hash","hash","hash","hash","hash","hash","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","mode","mode","new","new","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","random","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","stderr_char","stderr_float","stderr_int","stdin_char","stdin_float","stdin_int","stdout_char","stdout_float","stdout_int","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","Architecture","CompiledTarget","build_core","build_op","build_std","build_std_op","c","declare_proc","end","get","indentation","name","op","peek","poke","post_funs","postlude","postop","pre_funs","prelude","put","std_op","supports_floats","supports_input","supports_output","version","C","borrow","borrow_mut","declare_proc","default","deref","deref_mut","drop","end","from","get","init","into","name","op","peek","poke","post_funs","postlude","postop","prelude","put","std_op","supports_floats","supports_input","supports_output","try_from","try_into","type_id","version","ACos","ASin","ATan","Add","Add","Alloc","And","ArithmeticRightShift","BitwiseAnd","BitwiseNand","BitwiseNot","BitwiseOr","BitwiseXor","Call","Call","Comment","CoreInterpreter","CoreOp","CoreOp","CoreProgram","Cos","Dec","Deref","Device","Div","Div","Else","End","Error","ExpectedCore","Free","Function","Get","If","Inc","Index","IsNonNegative","IsNonNegative","LeftShift","Load","LogicalRightShift","Move","Mul","Mul","Neg","Neg","Not","Offset","Or","Peek","Poke","Pow","Put","Refer","Rem","Rem","Return","Set","Set","Sin","StandardDevice","StandardInterpreter","StandardOp","StandardProgram","Store","Sub","Sub","Swap","Tan","TestingDevice","ToFloat","ToInt","UnsupportedInstruction","VirtualMachineProgram","Where","While","add_binding","as_float","as_int","begin_else","begin_function","begin_if","begin_while","bitwise_nand","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","call","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","code","code","code","comment","default","default","default","default","default","default","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","drop","drop","drop","drop","drop","drop","drop","drop","drop","end","eq","eq","eq","eq","eq","ffi","ffi_call","ffi_call","ffi_call","ffi_call","ffi_channel","flatten","flatten","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","get","get","get","get","get_functions","get_functions","get_main","get_main","get_main_and_functions","get_main_and_functions","hash","hash","index","init","init","init","init","init","init","init","init","init","input","into","into","into","into","into","into","into","into","into","is_non_negative","load_vector","move_pointer","new","new","new","new_raw","op","op","op","output","output_str","output_vals","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","peek","peek","peek","peek","poke","poke","poke","poke","put","put","put","put","refer","restore","ret","run","run","save","set_float_register","set_float_vector","set_register","set_vector","std_op","std_op","std_op","store_vector","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","where_is_pointer"],"q":[[0,"sage"],[10,"sage::asm"],[65,"sage::asm::core"],[207,"sage::asm::core::CoreOp"],[348,"sage::asm::globals"],[376,"sage::asm::location"],[416,"sage::asm::std"],[510,"sage::asm::std::StandardOp"],[565,"sage::frontend"],[566,"sage::lir"],[1901,"sage::lir::Declaration"],[1903,"sage::lir::Error"],[1911,"sage::parse"],[1944,"sage::side_effects"],[1946,"sage::side_effects::ffi"],[1974,"sage::side_effects::io"],[2280,"sage::targets"],[2306,"sage::targets::c"],[2336,"sage::vm"],[2640,"alloc::string"],[2641,"core::fmt"],[2642,"core::fmt"],[2643,"core::option"],[2644,"core::cmp"],[2645,"core::any"],[2646,"serde::de"],[2647,"core::hash"],[2648,"alloc::vec"],[2649,"alloc::string"],[2650,"core::convert"],[2651,"alloc::boxed"],[2652,"alloc::collections::btree::map"],[2653,"std::collections::hash::map"],[2654,"std::collections::hash::set"],[2655,"core::ops::function"]],"d":["The UNICODE character art for the logo of the language.","The UNICODE character art for the logo of the language, …","The value of the NULL pointer constant.","Assembly Module","","LIR (Low Intermediate Representation) Module","Parsing Module","Side Effects Module","Targets Module","Virtual Machine Module","","A frontend to both the CoreProgram and StandardProgram …","","","","","","","An error generated by assembling some assembly language …","","","","","","","","","","The given global was not defined.","The given label was not defined.","The given instruction was not expected, or cannot be used …","The given instruction did not have a matching “end”. …","Is this standard assembly operation supported by the …","An error generated by the virtual machine.","","","","","Insert a comment into the program.","Core Assembly Variant","Get the current instruction number.","","","","","","","","Returns the argument unchanged.","Get the operation at the given instruction number.","Assembly Global Variables","","Calls U::from(self).","Is the given label defined yet in the operations? I.E., …","Assembly Memory Location","Log all the instructions after the given instruction …","Insert a core operation into the program.","","Standard Assembly Variant","Attempt to insert a standard operation into the program. …","","","","","","Add an integer value from a source location to a …","Logical “and” a destination with a source value.","Arithmetic right shift a destination by a source value. …","Store a list of values at a source location. Then, store …","","","","","","","Get a value in memory and call it as a label ID.","Call a function with a given label.","","Store the comparison of “a” and “b” in a …","Write a set of values to a memory location.","Copy a number of cells from a source referenced location …","A core instruction of the assembly language. These are …","An assembly program composed of core instructions, which …","Decrement the integer value of a location.","Divide a destination location by a source value.","Divide a destination location by a source value. Store the …","Add an “else” clause to an “if the value is not zero…","Terminate a function declaration, a while loop, an if …","Declare a new label.","Get a value from the input device / interface and store it …","Get the address of a location, and store it in a …","Declare a global variable.","Begin an “if the value is not zero” statement over a …","Increment the integer value of a location.","Get the address of a location indexed by an offset stored …","Perform dst = a == b.","Perform dst = a > b.","Perform dst = a >= b.","Perform dst = a < b.","Perform dst = a <= b.","Perform dst = a != b.","Left shift a destination by a source value.","Logical right shift a destination by a source value. This …","Many instructions to execute; conveniently grouped …","Copy a value from a source location to a destination …","Multiply a destination location by a source value.","Negate an integer.","Make this pointer point to the next cell (or the nth next …","Replace a value in memory with its boolean complement.","Logical “or” a destination with a source value.","Pop a number of cells from the stack and store it in a …","Pop a number of cells from a specified stack and store it …","Make this pointer point to the previous cell (or the nth …","Push a number of cells starting at a memory location on …","Get the address of a location and push it to the stack.","Push a const to the stack.","Push a number of cells starting at a memory location onto …","Put a value from a source register to the output device / …","Store the remainder of the destination modulus the source …","Return from the current function.","Set the value of a register, or any location in memory, to …","Set the value of a register, or any location in memory, to …","Subtract a source integer value from a destination …","Swap the values of two locations.","Perform a SIMD addition over a vector of integers. This …","Perform a vector “And” operation. This will perform a …","Perform a SIMD arithmetic right shift operation over a …","","","","","","","Decrement a vector of integers.","Perform a SIMD division over a vector of integers. This …","Perform a SIMD “is >= zero” operation over a vector of …","Increment a vector of integers.","Perform a SIMD pointer index operation over a vector of …","Perform a SIMD left shift operation over a vector of …","Perform a SIMD logical right shift operation over a vector …","Perform a SIMD multiplication over a vector of integers. …","Negate a vector of integers using SIMD.","Perform a vector “Not” operation. This will replace …","Perform a SIMD pointer arithmetic operation over a vector …","Perform a vector “Or” operation. This will perform a …","Perform a SIMD remainder over a vector of integers. This …","Set the vector values of a destination.","Perform a SIMD subtraction over a vector of integers. This …","Begin a “while the value is not zero” loop over a …","Assemble a program of core assembly instructions into the …","","","","","","","","","","","The list of core assembly instructions in the program.","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","Calls U::from(self).","Calls U::from(self).","","Create a new program of core assembly instructions.","","","","Push a string literal as UTF-8 to the stack.","Put a string literal as UTF-8 to the output device.","","","Allocate a string on the stack, and store its address in a …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","A lookup for all the global variables in an assembly …","Add a global variable to the list of globals.","","","","","Create a new empty Globals lookup.","","","","","","","Returns the argument unchanged.","Get the location, and size of a global variable.","Get the location of a global variable.","Get the size of a global variable. This is the number of …","Get the size of the global variables. This is the number …","","Calls U::from(self).","Create a new empty Globals lookup.","Resolve the global variables in a location to produce an …","","","","","","","The “A” general purpose register.","A fixed position in the tape (a constant address known at …","The “B” general purpose register.","The “C” general purpose register.","The “D” general purpose register.","The “E” general purpose register.","The “F” general purpose register.","The frame pointer register.","The Global Pointer register. This is used to access global …","A global variable.","Use the value of a cell on the tape as an address. For …","A location in memory (on the tape of the virtual machine).","Go to a position in memory, and then move the pointer …","","The stack pointer register.","","","","","","Get the location of the value pointed to by this location.","","","","","","","","Returns the argument unchanged.","","","Calls U::from(self).","Get the location offset by a constant number of cells from …","","","","","","","","Perform inverse Cos on a cell (float) and store the result …","Perform inverse Sin on a cell (float) and store the result …","Perform inverse Tan on a cell (float) and store the result …","Add the source cell (float) to the destination cell …","Take the value in the operand cell. Allocate that number …","Call a foreign function.","Write some constant values to a location on the tape","Execute a core instruction.","Perform Cos on a cell (float) and store the result in the …","Divide the destination cell (float) by the source cell …","Free the memory allocated at the address stored in the …","Perform dst = a > b.","Perform dst = a < b.","Multiply the source cell (float) by the destination cell …","Negate the value of a cell (float) and store the result in …","Raise a cell (float) to the power of another cell (float).","Push some constant values to the stack.","Perform the modulo operation on the destination cell …","Set the value of a cell to a constant float.","Perform Sin on a cell (float) and store the result in the …","Take the square root of a cell (float).","A standard instruction of the assembly language. These are …","A program composed of standard instructions, which can be …","Subtract the source cell (float) from the destination cell …","Perform Tan on a cell (float) and store the result in the …","Take the integer value stored in a cell and store the …","Take the float value stored in a cell and store the …","Perform a SIMD floating point inverse cosine operation.","Perform a SIMD floating point inverse sine operation.","Perform a SIMD floating point inverse tangent operation.","Perform a SIMD floating point addition operation.","Perform a SIMD floating point cosine operation.","Perform a SIMD floating point division operation.","Perform a SIMD floating point greater than or equal to …","Perform a SIMD floating point multiplication operation.","Perform a SIMD floating point negation operation.","Perform a SIMD floating point power operation.","Perform a SIMD floating point remainder operation.","Set the vector values of a destination.","Perform a SIMD floating point sine operation.","Perform a SIMD floating point subtraction operation.","Perform a SIMD floating point tangent operation.","Assemble the program into a virtual machine program.","","","","","","","","","The list of standard assembly instructions in the program.","Get the current instruction number.","","","","","","","","","","","","","","","","Returns the argument unchanged.","","Returns the argument unchanged.","Get the operation at the given instruction number.","","","Calls U::from(self).","Calls U::from(self).","Is the given label defined yet in the operations?","Create a new program of core assembly instructions.","Add a core operation to the program.","","","","","Add a standard operation to the program.","","","","","","","","","","","The first cell in the comparison (left hand side).","The first cell in the comparison (left hand side).","The second cell in the comparison (right hand side).","The second cell in the comparison (right hand side).","The beginning of the constant data.","The destination cell.","The destination cell.","The destination cell.","The destination cell.","The destination cell.","The destination cell.","The destination cell.","The destination cell.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","The source cell.","The source cell.","The source cell.","The source cell.","The source cell.","The source cell.","","","","","","","","The constant data.","","","","","A boolean “And” operation between two values.","An error with some annotation about the source code that …","","An expression along with data about its source code …","An annotation for metadata about an LIR expression. This …","Unchecked access to a value. This is used to override …","A type reserved by the compiler. This type is equal to any …","Apply a function with some arguments.","A type that constructs a concrete type from a polymorphic …","Tried to apply a non-procedure to some arguments.","Tried to apply a non-template type to some arguments.","An arithmetic operation.","An array of constant values.","An array of expressions.","An array of a given type, with a constant size.","Cast a constant expression to another type.","Cast an expression to another type.","An error caused by trying to assemble invalid code …","An assignment operation. This is used to implement …","A trait used to implemented an assignment operation.","Perform an assignment operation on two expressions.","A trait used to implement a binary operation.","Perform a binary operation on two expressions.","A boolean “BitwiseAnd” operation between two values.","A boolean “BitwiseNand” operation between two values.","A boolean “BitwiseNor” operation between two values.","","A boolean “BitwiseOr” operation between two values.","A boolean “BitwiseXor” operation between two values.","A constant boolean value.","The type of a boolean value.","An annotation for compiler-generated code.","An annotation for a constant.","A constant integer value representing a cell on the tape.","The type of the most basic unit of memory.","A constant chararacter.","The type of a character.","A comparison operation between two values.","A trait which allows an LIR expression to be compiled to …","Tried to compile a polymorphic procedure without …","Is this expression compiler-generated?","A constant expression.","A compiletime expression.","A constant expression.","","Is this expression a constant?","A builtin pseudo-procedure implemented in the core …","A builtin implemented in handwritten core assembly.","Recursion depth exceeded when trying to confirm a type’s …","An annotation for dead code.","Get the Union data associated with a tagged union …","Is this expression dead code?","","A declaration of a variable, function, type, etc.","Bind a list of types in a constant expression.","Declare any number of variables, procedures, types, or …","","Dereference this expression (i.e. get the value it points …","Store an expression to an address (a pointer).","Tried to dereference a non-pointer.","","","Duplicate implementations of a member for a type","An enumeration of a list of possible named values. A …","A tagged union of constant values.","A tagged union: a typechecked union of different variants. …","An enumeration of a list of possible types. This is a sum …","An environment under which expressions and types are …","","An LIR compilation error.","TODO: Add variants for LetProc, LetVar, etc. to support …","A foreign function declaration.","A typed procedure which calls a foreign function. This is …","A foreign function interface binding.","A constant floating point value.","The floating-point number type.","Import an element from a module.","","","Get the size of something in memory (number of cells).","Get the type associated with a value under a given …","","","An if-then-else expression.","An if-let expression.","Immutable access to a value. This is the default way to …","Declare associated constants and procedures for a type.","Index an array or pointer with an expression that …","A constant integer value.","The integer type.","Invalid type casting expression.","Invalid assignment operation (assign, add_assign, …","Invalid assign op types (incorrect types).","Invalid binary operation (add, subtract, and, or) …","Invalid binary op types (incorrect types).","Invalid constant expression.","Invalid Index expression (incorrect types).","Tried to match over an expression that cannot be matched …","Cannot monomorphize a constant expression.","Tried to use a pattern that is not valid for the given …","Tried to use a pattern that is not valid for the given …","Invalid Refer expression. The compiler was not able to …","Invalid number of template arguments to a type.","Invalid ternary operation (if) expression (incorrect …","Invalid ternary op types (incorrect types).","Invalid unary operation (negate, not) expression …","Invalid unary op types (incorrect types).","An annotation for live code.","","","Bind a type to a name in a temporary scope.","The source code location of the expression.","Many annotations can be attached to an expression. This is …","Many declarations.","A block of expressions. The last expression in the block …","A match expression.","Get an attribute of a constant expression.","Get a field or member from a structure, union, or tuple. …","Tried to access an undefined member of a tuple, struct, or …","Mismatched mutability","Mismatched types","Declare a module","Monomorphize a constant expression with some type …","","Mutability of a pointer. This is used to provide type …","Mutable access to a value.","A constant expression that evaluates to None. This …","","Tried to create an array with a negative length.","The type of an expression that will never return, or doesn…","","Invalid pattern for a match expression.","Got another type when expecting an integer, bool, or char.","Expected a symbol, but got something else.","No annotation.","The unit, or “void” instance.","The type of void expressions.","A boolean “Not” operation on a value.","","The null pointer constant.","A constant enum variant.","A boolean “Or” operation between two values.","A pattern which can be matched against an expression.","","A pointer to another type.","A polymorphic, parametric type. This type is used with the …","A polymorphic procedure.","A polymorphic procedure declaration.","A polymorphic procedure of LIR code which can be applied …","","A procedure.","A procedure declaration.","A procedure with a list of parameters and a return type.","A monomorphic procedure of LIR code which can be applied …","Print a value to a given output.","Recursion depth exceeded when trying to evaluate a …","Recursion depth exceeded when trying to confirm a type’s …","Reference this expression (i.e. get a pointer to it).","","Return a value from a function.","This is the maximum number of times a type will be …","Simplify an expression while maintaining structural …","Get the size of an expression’s type (in cells) as a …","Tried to get the size of a template type.","Get the size of a type (in cells) as a constant int.","A builtin pseudo-procedure implemented in the standard …","A builtin implemented in handwritten standard assembly.","A static variable declaration.","A structure of constant values.","A structure of fields to expressions.","","A tuple with named members. This is a product type.","","A named constant.","","A named type.","A symbol was used, but not defined.","An annotation for a temporary.","Get the Enum value of the tag associated with a tagged …","","Is this expression a temporary?","A trait used to implement a ternary operation.","Perform a ternary operation on three expressions.","A tuple of constant values.","A tuple of expressions.","","A heterogenous collection of types. This is a product type.","The representation of a type in the LIR type system.","A type as a constant expression.","A type declaration.","A trait object. This is internally represented as an …","A trait used to enforce type checking.","A type was used, but not defined.","Get the type of an expression. (as an array of chars)","Tried to define a type that already exists.","An annotation for user-generated code.","A trait used to implement a unary operation.","Perform a unary operation on two expressions.","","A union of constant values.","A union: a collection of named fields. The Type value is …","A union of a list of possible types mapped to named …","This type is identified by its name. Most types are …","Tried to instantiate a type that cannot be sized. This is …","Expression uses an operation unsupported by the target.","Unused expression returned a non-None value.","A variable declaration.","A variable declaration with a pattern.","","The variant of an enum is not defined.","A constant, compile time if-then-else expression.","Create a while loop: while the first expression evaluates …","","","Add this expression to another.","","","","Construct a new pattern which binds to several alternate …","Logical and this expression with another.","Annotate an error with some metadata.","Annotate this constant expression with a source code …","An annotated expression with some metadata.","Apply this procedure or builtin to a list of expressions …","Apply this expression as a procedure to some arguments.","","This associated function returns whether or not a set of …","The arguments of the builtin. These will be typechecked …","The arguments of the builtin. These will be typechecked …","Try to get this constant expression as a boolean value.","Try to get this constant expression as a character.","Try to get this constant expression as a float.","Try to get this constant expression as an integer.","Try to get this constant expression as a symbol (like in …","Cast an expression as another type.","Cast an expression as another type.","Perform an AssignOp on this expression.","Perform an AssignOp on this expression.","BitwiseAnd this expression with another.","BitwiseOr this expression with another.","BitwiseAnd this expression with another.","BitwiseAnd this expression with another.","","BitwiseOr this expression with another.","","Bitwise this expression with another.","The list of assembly instructions to be pasted into the …","The list of assembly instructions to be pasted into the …","Construct a new pattern which matches a constant boolean.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Checks if the operation can be applied to the given types.","Checks if the operation can be applied to the given type.","Checks if the operation can be applied to the given types.","Checks if the operation can be applied to the given types.","","","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this unary operation be applied to the given type?","Can this unary operation be applied to the given type?","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this unary operation be applied to the given type?","Can this unary operation be applied to the given type?","Can this unary operation be applied to the given type?","Can this unary operation be applied to the given type?","Can this unary operation be applied to the given type?","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Can this type be cast to another type?","Can a pointer of this mutability decay to a pointer of …","Can this type decay into another type?","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Clones the operation into a boxed trait object.","Clones the operation into a boxed trait object.","Clones the operation into a boxed trait object.","Clones the operation into a boxed trait object.","","","","Clone this operation into a trait object.","Clone this binary operation into a box.","Clone this binary operation into a box.","Clone this binary operation into a box.","","Clone this binary operation into a box.","Clone this binary operation into a box.","","Clone this operation into a box.","Clone this operation into a box.","Clone this binary operation into a box.","Clone this operation into a box.","Clone this operation into a box.","Clone this operation into a box.","Clone this operation into a box.","Clone this operation into a box.","Clone this operation into a box.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Compile the expression into an assembly program.","Compile the expression into an assembly program.","Compiles the operation on the given expressions.","Compiles the operation on the given expressions.","Compiles the operation on the given expression.","Compiles the operation on the given expression.","Compiles the operation on the given expressions.","Compiles the operation on the given expressions.","Compiles the operation on the given expressions.","Compiles the operation on the given expressions.","Compiles the operation on the given expressions.","Compile the assignment operation.","","","","","","","","Compiles the operation on the given types. (Generates the …","Compiles the operation on the given type. (Generates the …","Compiles the operation on the given types. (Generates the …","Compiles the operation on the given types. (Generates the …","","","Compile the binary operation.","Compile the assignment operation.","Compile the binary operation.","Compile the binary operation.","Compile the binary operation.","","Compile the binary operation.","Compile the binary operation.","Compile the binary operation.","Compile the unary operation.","Compile the unary operation.","Compile the binary operation.","Compile the binary operation.","Compile the unary operation.","Compile the unary operation.","Compile the unary operation.","Compile the unary operation.","Compile the unary operation.","Does this type contain a symbol with the given name? This …","","Let-bind the pattern to the given expression. This will …","","","Define multiple types with the given names under this …","Define a variable in the current scope. This will …","","","","","","","Dereference this expression (i.e. get the value it points …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Dereference this expression (i.e. get the value it points …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","","Divide this expression by another.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Is this expression greater than another?","","","","","","","","","","","","","","","","","","","","","","","","","Are two types structurally equal?","Evaluates the operation on the given constant expressions.","Evaluates the operation on the given constant expression.","Evaluates the operation on the given constant expressions.","Evaluates the operation on the given constant expressions.","Evaluate this constant expression at compile time, and get …","","","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this unary operation on the given constant values.","Evaluate this unary operation on the given constant values.","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this unary operation on the given constant values.","Evaluate this unary operation on the given constant values.","Evaluate this unary operation on the given constant values.","Evaluate this unary operation on the given constant values.","Evaluate this unary operation on the given constant values.","Get a field from a structure, union, or tuple.","Get a field from a structure, union, or tuple.","Construct a new pattern which matches a constant float.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","","","","","","","","","","","","Returns the argument unchanged.","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","","Is this expression greater than or equal to another?","","Get the arguments of the procedure.","","Get the map of new variables and their types which are …","Get the body of the procedure.","Get the type of a branch with a given expression matched …","Get the name of the procedure known to the LIR front-end.","Get the mangled name of the procedure. The procedure’s …","","","Get the name of this polymorphic procedure. This is not …","Get the return type of the procedure.","Get the first argument’s mutability (if it is a pointer)","Get the size of something in memory (number of cells).","Get the size of something in memory (number of cells).","Get the size of something in memory, but limit the number …","","","","","","","","","","Get the type associated with a value under a given …","Get the type associated with a value under a given …","Get the type of a value under a given environment and check","","","","","","","","Get the type of an associated constant of a type.","Is this expression greater than another?","","","Does this type have an element type matching the supplied …","Does this annotation have a location?","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Index an array or pointer with an expression that …","Generate an if letexpression, which matches a given expr, …","Create an if-then-else statement with this expression as …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Construct a new pattern which matches a constant integer.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Is this type an irreducible, atomic type?","Is this compiler-generated?","","Is this data protected against mutation?","Is this dead code?","Is this pattern exhaustive?","Is this annotation a location?","","","Can this data be accessed mutably?","Is this annotation none?","","","","Is first argument of function a reference?","Is this type in a simple form? A simple form is a form …","Is this a temporary?","Is this expression less than or equal to another?","Create a let-bound type.","Create a let binding for a constant expression.","Create several const bindings at onces.","Create a proc binding for a procedure.","Create several proc bindings at onces.","Create a let binding for an type.","Create several type bindings at onces.","Create a let binding for an expression.","Create a let binding for an expression, and define …","Get the location of this annotation.","Is this expression less than another?","Create a collection of declarations","Generate an expression which evaluates a match expression, …","Create a module with a given name and a list of …","","Take some type arguments and produce a monomorphized …","Multiply this expression by another.","","","","","","","","","The name of the builtin. This isn’t used in compilation, …","The name of the builtin. This isn’t used in compilation, …","Get the remainder of this expression divided by another.","Is this expression greater than or equal to another?","Create a new assignment operation.","Create a new FFI procedure.","Construct a new procedure with a given list of arguments …","Construct a new polymorphic procedure with type …","Logical not this expression.","Logical or this expression with another.","","","","","","","","","","","","","","","","","","","","","","","Perform type applications if possible.","Construct a new pattern which matches a pointer.","Get the power of this expression to another.","","","Construct a procedure.","Push this procedure’s label to the stack.","Reference this expression (i.e. get a pointer to it).","Get the remainder of this expression divided by another.","The return value the builtin will leave on the stack after …","The return value the builtin will leave on the stack after …","Gets the type of the operation on the given expressions.","Gets the type of the operation on the given expressions.","Gets the type of the operation on the given expression.","Gets the type of the operation on the given expression.","Gets the type of the operation on the given expressions.","Gets the type of the operation on the given expressions.","Gets the type of the operation on the given expressions.","Gets the type of the operation on the given expressions.","","","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this unary …","Get the type of the result of applying this unary …","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this unary …","Get the type of the result of applying this unary …","Get the type of the result of applying this unary …","Get the type of the result of applying this unary …","Get the type of the result of applying this unary …","","","","","","","","","","","","","This is just for debugging purposes. This sets the common …","Simplify an expression while maintaining structural …","Simplify an expression while maintaining structural …","","","","Simplify until the type is concrete.","Simplify a type until you can get its members.","Simplify a type until you can get its variants.","Simplify an expression until it matches a given function …","Simplify until the type is a polymorphic type.","","Simplify until the type passes the type checker.","Simplify a type until it’s a union.","Get the size of an expression.","","Construct a new pattern which matches a struct with a …","Create a structure of fields to expressions.","Subtract an expression from this expression.","Substitute a type for a given name in the environment.","","Substitute a type in a given expression.","","","","","","Substitute all occurences of a symbol with another type. …","","","Construct a new pattern which matches a symbol with a …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Construct a new pattern which matches a tuple of patterns.","Type check the expression.","Typechecks the operation on the given expressions.","Typechecks the operation on the given expressions.","Typechecks the operation on the given expression.","Typechecks the operation on the given expression.","Typechecks the operation on the given expressions.","Typechecks the operation on the given expressions.","Typechecks the operation on the given expressions.","Typechecks the operation on the given expressions.","","","","Type-check a pattern match of an expression against this …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Apply a unary operation to this expression.","Evaluate a variable in the current scope.","Evaluate a variable in the current scope.","Calculate the integral value of a variant in an enum.","Create a while statement with this expression as the …","Construct a new pattern which matches any expression.","Return this expression, but with a given declaration in …","Return this expression, but with a given declaration in …","","","","","","","","","","","","","A struct representing a location in the source code. This …","","","","","","","","","","","","","","Returns the argument unchanged.","","","","Calls U::from(self).","","","","Parse Core and Standard variants of assembly source code. …","Parse frontend sage code into an LIR expression.","","Parse LIR code as an LIR expression.","Parse Core and Standard variants of virtual machine source …","","","","","","","Foreign Function Interface","I/O Module","This is an FFI binding, which is used to call a foreign …","","","","","","","","","","","","","Returns the argument unchanged.","","","","Calls U::from(self).","","Create a new FFI binding.","","","","","","","","","Input from an accelerometer (in meters per second per …","Input from altitude sensor (in meters)","Electrical device input modes (These should typically be …","Electrical device output modes Set the voltage of a given …","The different axes an input or output might use.","Input from a barometer (pressure in atmospheres)","Ring a bell (in hertz)","Black","Set the pressure of a given blower (in atmospheres)","Blue","Blue light intensity (in lux)","Input from a light sensor (in lux)","Lighting device output modes Set the brightness of a given …","Input from a button (0=not pressed, 1=pressed)","Sound output modes Ring a given buzzer (in hertz)","The channel to use for a given I/O mode.","Clear the display","Physical sensor input modes (These should typically be …","The different output colors a program might use.","Input from a compass (degrees)","Input from a conductivity sensor (in siemens per meter)","Turn a cooler on or off (0=off, 1=on)","Custom output modes A custom input mode (for use with a …","Custom output modes A custom output mode (for use with a …","Cyan","User input modes (These should typically be used for games …","Input from depth sensor (in meters)","Input from a digital input (0=low, 1=high)","Set the state of a given digital output (0=low, 1=high)","The different directions a D-Pad a might use.","","Set the pressure of a given fan (in atmospheres)","Input from a flow sensor (in liters per second)","Green","Green light intensity (in lux)","Input from a gyroscope (in degrees per second) around a …","Turn a heater on or off (0=off, 1=on)","Input from a humidity sensor (in percent)","An input source for a program.","The different types of input modes a program might use.","Input from a JoyStick the degree of displacement in a …","Input from keyboard (ASCII character)","","Magenta","Input from a magnetometer (in teslas) in a given axis","Input from a microphone (frequency in hertz)","Set the speed of a given motor (in revolutions per minute)","Move the cursor down on the display","Move the cursor left on the display","Move the cursor right on the display","Move the cursor up on the display","Play a given note (in hertz)","Input from an odometer (in meters)","Orange","An output destination for a program.","The different types of output modes a program might use.","Input from a pH sensor (in pH)","Input from a position sensor in a given axis (x, y, z)","Set the pressure of a given vacuum/pressurizer …","Engineering / Science sensor input modes Input from a …","Alternative output modes for standard output Printer …","Printer (float)","Printer (integer)","Input from a distance sensor (in meters)","Set the pressure of a given pump (in atmospheres)","RGB ","Input from a rain gauge (in millimeters)","Special input modes A random number","Red","Environment sensor input modes (These should typically be …","","Set the position of a given servo (in radians)","Write a character to the display","Set the cursor column on the display","Set the color of a given pixel on the display","Set the cursor row on the display","Set the polarity of a solenoid (0=off, 1=on)","Set the frequency of a given speaker (in hertz)","Set the volume of a given speaker (in percent)","Navigation input modes (These should typically be …","Standard error (ASCII character)","Standard error (float)","Standard error (integer)","Standard input modes (The standard interface is typically …","Standard input (float)","Standard input (integer)","Standard output modes Standard output (ASCII character)","Standard output (float)","Standard output (integer)","Robotics device output modes Set the position of a given …","Set the temperature of a given heating/cooling device …","Input from a thermometer (degrees K)","Input from a UV sensor (in watts per square meter)","","Display output modes Update the display","Set the position of a given valve (0=closed, 1=open)","Input from a volume sensor (in liters)","Input from a weight sensor (in kilograms)","White","Input from a wind direction sensor (in degrees)","Input from a wind speed sensor (in meters per second)","","","Yellow","","","","","","","","","","","","","","","","","","The channel to use for the input.","The channel to use for the output.","The time (in seconds) since the program started","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","","","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","The mode of the input.","The mode of the output.","Create a new input source.","Create a new output destination.","","","","","","","","","A random number","","","","","","","","","Output to STDERR (ASCII character)","Output to STDERR (float)","Output to STDERR (integer)","Input from STDIN (ASCII character)","Input from STDIN (float)","Input from STDIN (integer)","Output to STDOUT (ASCII character)","Output to STDOUT (float)","Output to STDOUT (integer)","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","A trait for a target architecture to be compiled to.","Implement a compiler for the given target.","Compile the core variant of the machine code (must be …","","Compile the standard variant of the machine code (should …","","C Target","Compile the declaration of a procedure.","Compile an End instruction (with the matching If or While …","Get a value from the given input stream (mode + channel).","The string used for indentation.","The name of the target architecture.","Compile a CoreOp instruction.","Peek a value from the device connected to the program.","Poke a value to the device connected to the program.","The code after the function definitions.","The code after the program ends.","The code after each instruction.","The code before the function definitions.","The code before the program starts.","Put a value to the given output stream (mode + channel).","Compile a StandardOp instruction.","Whether or not the target architecture supports floating …","Whether or not the target architecture supports the given …","Whether or not the target architecture supports the given …","The version of the target architecture.","The type for the C target which implements the Target …","","","","","","","","","Returns the argument unchanged.","","","Calls U::from(self).","","","","","","","","","","","","","","","","","","Store the inverse-cosine of the register (as a float) into …","Store the inverse-sine of the register (as a float) into …","Store the inverse-tangent of the register (as a float) …","Add the value pointed to on the tape to the register. The …","Add the value pointed to on the tape to the register (as …","Take the value of the register, and allocate that number …","Boolean-and the register and the value pointed to on the …","Interpret the register’s value as a signed integer. …","Perform bitwise and on the cell and the value pointed to …","Perform bitwise nand on the cell and the value pointed to …","Bitwise not the register. Store the result in the register.","Perform bitwise or on the cell and the value pointed to on …","Perform a bitwise xor on the cell and the value pointed to …","Calls the nth function defined in the program, where n is …","Call a foreign function interface function.","A comment in the machine code (not in the compiled output).","The interpreter which runs the virtual machine program.","An individual core virtual machine instruction.","Execute a core instruction.","A program of only core virtual machine instructions.","Store the cosine of the register (as a float) into the …","Decrement the register.","The pointer is made equal to the value pointed to on the …","Create an input / output device for the virtual machine …","Divide the register by the value pointed to on the tape. …","Divide the register by the value pointed to on the tape …","Begin an “else” conditional.","End a conditional.","An error generated by the virtual machine.","When the virtual machine attempts to get the program as …","Free the memory pointed to by the register.","Create a new function.","Get a value from an input source and store it in the …","Begin an “if the register is not zero” conditional.","Increment the register. The argument is the size of the …","Interpret the register’s value as a pointer to a cell. …","Make the register equal to 1 if the register is …","Make the register equal to the integer 1 if the register …","Left shift the cell by the value pointed to on the tape. …","Store the value pointed to on the tape to the register.","Logical right shift the cell by the value pointed to on …","Move the pointer on the tape by a number of cells.","Multiply the register by the value pointed to on the tape. …","Multiply the register by the value pointed to on the tape …","Negate the register. The argument is the size of the …","Negate the value of the register (as a float).","Boolean-not the register (0 if the register is non-zero, 1 …","Interpret the register’s value as a pointer to a cell. …","Boolean-or the register and the value pointed to on the …","Get a value from the input interface / device and store it …","Write the value of the register to the output interface / …","Store the value of the register (as a float) to the power …","Write the value of the register to an output source.","The last “deref” operation is undone; the pointer is …","Store the remainder of the register and the value pointed …","Store the remainder of the register and the value pointed …","Return from the current function.","Set the register equal to a constant value.","Set the register equal to a constant floating point value.","Store the sine of the register (as a float) into the …","A device used for standard input and output. This simply …","The interpreter which runs the standard variant of virtual …","An individual standard virtual machine instruction.","A program of core and standard virtual machine …","Store the register to the value pointed to on the tape.","Subtract the value pointed to on the tape from the …","Subtract the value pointed to on the tape from the …","Swap the value of the register with the value pointed to …","Store the tangent of the register (as a float) into the …","A device used for testing the compiler. This simply keeps …","Convert the register from an integer to a float.","Convert the register from a float to an integer.","When an instruction is unsupported for a given …","An interface to conveniently create virtual machine …","Store the value of the pointer to the register.","Begin a “while the register is not zero” loop.","","A function to reinterpret the bits of an integer as a …","A function to reinterpret the bits of a float as an …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","FFI call to the device. This will get the FFI binding for …","","","","","Flatten a core program so that all of its functions are …","Flatten a core program so that all of its functions are …","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Get the next input (from a given input source).","","","","Get the code for each function.","Get the code for each function.","Get the code outside of any functions.","Get the code outside of any functions.","Get the code outside of any functions, and the code for …","Get the code outside of any functions, and the code for …","","","","","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","","Create a new testing device with some given sample input.","","","","","","Get the output of the testing device as a string (ascii).","","","","","","","Peek at the next value in the FFI buffer for the FFI …","","","","Poke a value into the FFI buffer for the FFI function …","","","","Put the given value to the given output destination.","","","","","","","Run a core program using this interpreter and its device.","Run a core program using this interpreter and its device.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"i":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,3,0,3,1,1,1,1,1,1,1,1,3,0,1,1,3,0,3,3,1,0,3,1,1,1,1,1,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,0,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,17,17,10,17,10,17,10,17,10,17,10,17,17,17,17,10,17,10,17,10,17,10,17,10,17,17,10,10,17,10,17,17,10,17,10,17,10,17,17,17,17,10,10,10,17,10,10,17,17,10,17,10,17,10,17,10,17,10,105,106,107,108,109,110,111,112,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,105,106,107,108,109,110,111,145,146,147,148,149,150,151,152,153,154,155,156,157,158,115,142,143,158,114,122,123,124,125,126,129,130,131,132,133,137,138,139,140,141,142,143,159,144,152,153,154,155,156,157,159,144,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,130,131,134,135,136,137,138,139,140,143,159,145,147,148,149,150,151,152,153,154,155,156,145,146,0,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,0,25,0,0,0,0,0,0,0,25,25,0,25,0,0,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,28,28,11,28,11,28,11,28,11,28,28,28,28,11,28,11,28,11,28,11,28,11,28,28,11,11,28,28,11,28,28,11,28,11,28,28,28,28,11,28,11,28,28,11,28,11,28,11,28,11,28,11,160,161,160,161,162,163,164,165,166,167,168,160,161,169,170,171,172,173,174,175,176,177,178,179,180,181,182,169,170,171,172,173,174,175,176,177,178,179,180,181,182,163,164,165,166,167,168,169,170,171,172,173,175,182,162,0,0,49,37,0,36,35,30,0,67,34,30,34,36,36,0,35,30,34,35,30,36,0,0,30,0,30,0,0,0,0,0,0,35,34,38,38,35,34,35,34,0,0,36,38,31,0,30,37,38,0,35,36,38,0,38,59,0,35,30,0,30,30,36,59,49,36,34,35,30,34,0,57,0,0,31,0,35,35,34,31,31,0,0,0,57,57,30,30,67,31,30,35,34,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,38,57,57,34,38,38,31,30,30,35,30,36,36,36,31,35,49,0,67,30,0,36,34,0,36,36,36,38,35,34,0,57,35,35,0,0,37,34,34,35,31,0,49,35,31,34,0,0,36,36,30,49,30,34,0,35,36,35,0,35,31,35,30,37,34,49,35,37,34,36,38,0,35,38,0,30,35,30,37,34,0,35,31,34,0,36,35,36,38,0,30,36,35,30,34,34,36,36,36,31,31,37,36,30,30,37,31,30,31,33,34,37,30,36,35,30,35,30,34,37,68,69,35,35,35,35,35,35,30,30,30,30,30,30,30,38,30,38,30,68,69,37,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,43,43,44,44,45,45,46,46,34,67,34,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,43,44,45,46,38,47,48,51,52,53,54,55,56,57,58,59,60,63,64,65,66,67,74,74,43,43,44,44,45,45,46,46,47,50,74,35,30,68,69,70,71,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,34,59,37,33,67,33,33,38,33,36,35,31,30,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,38,33,36,35,31,30,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,38,35,31,30,37,68,69,70,71,72,67,34,43,43,44,44,45,45,46,46,59,30,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,43,44,45,46,38,35,31,30,30,47,48,51,52,53,54,55,56,57,58,59,60,63,64,65,66,37,68,69,70,71,72,67,34,34,43,44,45,46,35,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,35,30,37,38,33,33,36,36,35,35,31,31,30,30,47,47,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63,64,64,65,65,66,66,37,37,68,68,69,69,70,70,71,71,72,72,67,67,34,34,38,38,33,36,36,35,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,30,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,67,34,72,30,33,71,33,37,71,37,71,71,30,34,72,71,34,79,79,79,35,30,68,69,70,71,72,34,34,80,80,80,35,30,68,69,70,71,72,33,30,30,33,34,38,38,35,31,30,47,48,51,52,53,54,55,56,57,58,59,60,63,64,65,66,37,68,69,70,71,72,67,34,30,37,30,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,37,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,34,38,34,67,38,37,38,30,34,67,38,34,34,34,34,34,38,30,34,30,30,30,30,30,30,30,30,38,30,31,37,31,35,72,30,43,43,44,44,45,45,46,46,68,69,30,30,50,70,71,72,30,30,43,44,45,46,38,47,48,51,52,53,54,55,56,57,58,59,60,63,64,65,66,67,34,37,30,30,30,35,71,30,30,68,69,43,43,44,44,45,45,46,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,38,35,31,30,37,68,69,70,71,72,67,34,71,81,81,35,34,34,34,34,34,34,34,34,34,34,30,34,37,30,30,80,35,30,68,69,70,71,72,34,80,80,37,35,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,30,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,37,84,43,43,44,44,45,45,46,46,35,31,30,37,68,69,70,71,72,34,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,30,35,30,34,30,37,35,30,71,72,183,183,184,185,184,185,186,184,185,186,0,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,0,0,0,0,0,75,75,75,75,75,75,0,0,0,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,90,90,90,91,0,90,91,89,91,89,90,90,91,90,91,0,91,90,0,90,90,91,90,91,89,90,90,90,91,0,88,91,90,89,90,90,91,90,0,0,90,90,88,89,90,90,91,91,91,91,91,91,90,89,0,0,90,90,91,90,91,91,91,90,91,89,90,90,89,90,88,91,91,91,91,91,91,91,91,90,91,91,91,90,90,90,91,91,91,91,91,90,90,88,91,91,90,90,89,90,90,87,87,89,87,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,86,23,86,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,87,88,88,89,89,90,90,91,91,92,92,86,86,23,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,86,23,86,23,87,88,89,90,91,92,86,23,86,87,88,89,90,91,92,86,23,23,23,23,86,86,86,23,23,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,0,0,93,93,93,93,0,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,0,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,95,95,95,94,95,95,94,94,94,94,94,94,94,94,95,94,0,0,95,0,95,94,94,0,94,95,94,94,0,9,95,94,94,94,94,94,94,95,94,94,94,94,94,95,94,95,94,94,94,95,95,95,94,94,94,95,94,94,95,95,0,0,0,0,94,94,95,94,95,0,95,95,9,0,94,94,99,0,0,100,100,100,100,100,101,102,18,94,29,95,103,99,9,101,102,18,94,29,95,103,99,9,100,18,94,29,95,99,9,18,94,29,95,99,9,18,94,100,18,29,100,101,102,18,29,103,99,101,102,100,18,94,29,95,103,99,9,101,102,18,94,29,95,103,99,9,101,102,18,94,29,95,103,99,9,100,18,94,29,95,9,103,104,100,103,99,103,18,29,18,94,94,29,95,95,103,99,9,9,101,102,18,94,29,29,95,103,99,9,104,100,103,99,18,29,18,29,18,29,18,94,100,101,102,18,94,29,95,103,99,9,103,101,102,18,94,29,95,103,99,9,100,100,100,101,102,103,103,100,18,29,103,103,103,18,94,29,95,9,104,100,103,99,104,100,103,99,104,100,103,99,100,100,100,101,102,100,100,100,100,100,100,18,29,100,18,94,29,95,99,9,18,94,29,95,9,101,102,18,94,29,95,103,99,9,101,102,18,94,29,95,103,99,9,101,102,18,94,29,95,103,99,9,100],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[1,1],[[-1,-2],2,[],[]],[[3,4],2],0,[3,5],[5,-1,[]],[5,-1,[]],[5,2],[[1,1],6],[[1,7],8],[[1,7],8],[9,1],[-1,-1,[]],[[3,5],[[13,[[12,[10,11]]]]]],0,[[],5],[-1,-2,[],[]],[[3,14],6],0,[[3,14,14,5],2],[[3,10],2],[[1,1],[[13,[15]]]],0,[[3,11],[[12,[2,1]]]],[-1,-2,[],[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[17,5],[[12,[18,1]]]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[17,17],[10,10],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[17,17],15],[[10,10],15],0,[17,5],[[],17],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[-1,[[12,[17]]],19],[-1,[[12,[10]]],19],[5,2],[5,2],[[17,17],6],[[10,10],6],[[17,7],8],[[17,7],8],[[10,7],8],[[10,7],8],[-1,-1,[]],[-1,-1,[]],[[17,5],[[13,[[12,[10,11]]]]]],[[17,-1],2,20],[[10,-1],2,20],[[],5],[[],5],[-1,-2,[],[]],[-1,-2,[],[]],[[17,14],6],[[[21,[10]]],17],[[17,10],2],[[17,17],[[13,[15]]]],[[10,10],[[13,[15]]]],[-1,10,22],[[-1,23],10,22],[[17,-1],12,24],[[10,-1],12,24],[[25,-1],10,22],[[17,11],[[12,[2,1]]]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,4,[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[26,4,5],25],[-1,-2,[],[]],[-1,-2,[],[]],[26,26],[[-1,-2],2,[],[]],[[],26],[5,-1,[]],[5,-1,[]],[-1,[[12,[26]]],19],[5,2],[[26,7],8],[[26,7],8],[-1,-1,[]],[[26,14],[[13,[[2,[25,5,5]]]]]],[[26,14],[[13,[25]]]],[[26,14],[[13,[5]]]],[26,5],[[],5],[-1,-2,[],[]],[[],26],[[26,25],[[12,[25,1]]]],[[26,-1],12,24],[-1,-2,[],[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[25,25],[[-1,-2],2,[],[]],[[25,25],15],[25,25],[5,-1,[]],[5,-1,[]],[-1,[[12,[25]]],19],[5,2],[[25,25],6],[[25,7],8],[[25,7],8],[-1,-1,[]],[[25,-1],2,20],[[],5],[-1,-2,[],[]],[[25,27],25],[[25,25],[[13,[15]]]],[[25,-1],12,24],[-1,-2,[],[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[28,5],[[12,[29,1]]]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[28,28],[11,11],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],0,[28,5],[[],28],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[-1,[[12,[28]]],19],[-1,[[12,[11]]],19],[5,2],[5,2],[[28,28],6],[[11,11],6],[[28,7],8],[[28,7],8],[[11,7],8],[[11,7],8],[-1,-1,[]],[17,28],[-1,-1,[]],[[28,5],[[13,[[12,[10,11]]]]]],[[],5],[[],5],[-1,-2,[],[]],[-1,-2,[],[]],[[28,14],6],[[[21,[11]]],28],[[28,10],2],[[28,28],[[13,[15]]]],[[11,11],[[13,[15]]]],[[28,-1],12,24],[[11,-1],12,24],[[28,11],[[12,[2,1]]]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,4,[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[-1,[13,[14]],6,6],[[12,[30,4]]],22],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[31,-1],-2,[[32,[31]]],[]],[[30,-1],30,[[32,[30]]]],[[31,-1],2,[[32,[31]]]],[[33,34,-1,35],[[12,[2,36]]],22],[[34,33],[[12,[2,36]]]],[[[21,[37]]],37],[[30,-1],30,[[32,[30]]]],[[36,38],36],[[35,38],35],[[30,-1],30,[[32,[38]]]],[[35,[21,[30]]],30],[[30,[21,[30]]],30],[[34,[21,[34]]],34],[[30,[39,[37]],34,33],[[12,[6,36]]]],0,0,[[35,33],[[12,[6,36]]]],[[35,33],[[12,[40,36]]]],[[35,33],[[12,[41,36]]]],[[35,33],[[12,[42,36]]]],[[35,33],[[12,[4,36]]]],[[35,34],35],[[30,34],30],[[30,-1,-2],30,22,[[32,[30]]]],[[30,-1,-2],30,22,[[32,[30]]]],[[30,-1],30,[[32,[30]]]],[[30,-1],30,[[32,[30]]]],[[30,-1],30,[[32,[30]]]],[30,30],[[38,38],-1,[]],[[30,-1],30,[[32,[30]]]],[[38,38],2],[[30,-1],30,[[32,[30]]]],0,0,[6,37],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[[43,34,34,33],[[12,[6,36]]]],[[44,34,33],[[12,[6,36]]]],[[45,34,34,33],[[12,[6,36]]]],[[46,34,34,34,33],[[12,[6,36]]]],[[47,34,34,33],[[12,[6,36]]]],[[48,34,33],[[12,[6,36]]]],[[49,34,34,33],[[12,[6,36]]]],[[50,34,34,33],[[12,[6,36]]]],[[51,34,34,33],[[12,[6,36]]]],[[52,34,34,33],[[12,[6,36]]]],[[53,34,34,33],[[12,[6,36]]]],[[54,34,33],[[12,[6,36]]]],[[55,34,34,33],[[12,[6,36]]]],[[56,34,34,33],[[12,[6,36]]]],[[57,34,34,33],[[12,[6,36]]]],[[58,34,33],[[12,[6,36]]]],[[59,34,33],[[12,[6,36]]]],[[60,34,34,33],[[12,[6,36]]]],[[61,34,34,33],[[12,[6,36]]]],[[62,34,33],[[12,[6,36]]]],[[63,34,33],[[12,[6,36]]]],[[64,34,33],[[12,[6,36]]]],[[65,34,33],[[12,[6,36]]]],[[66,34,33],[[12,[6,36]]]],[[43,30,30,33],[[12,[6,36]]]],[[43,30,30,33],[[12,[6,36]]]],[[44,30,33],[[12,[6,36]]]],[[44,30,33],[[12,[6,36]]]],[[45,30,30,33],[[12,[6,36]]]],[[45,30,30,33],[[12,[6,36]]]],[[46,30,30,30,33],[[12,[6,36]]]],[[46,30,30,30,33],[[12,[6,36]]]],[[34,34,33],[[12,[6,36]]]],[[67,67],6],[[34,34,33],[[12,[6,36]]]],[38,38],[33,33],[36,36],[35,35],[31,31],[30,30],[47,47],[48,48],[49,49],[50,50],[51,51],[52,52],[53,53],[54,54],[55,55],[56,56],[57,57],[58,58],[59,59],[60,60],[61,61],[62,62],[63,63],[64,64],[65,65],[66,66],[37,37],[68,68],[69,69],[70,70],[71,71],[72,72],[67,67],[34,34],[43,[[73,[43]]]],[44,[[73,[44]]]],[45,[[73,[45]]]],[46,[[73,[46]]]],[47,[[73,[45]]]],[48,[[73,[44]]]],[49,[[73,[45]]]],[50,[[73,[43]]]],[51,[[73,[45]]]],[52,[[73,[45]]]],[53,[[73,[45]]]],[54,[[73,[44]]]],[55,[[73,[45]]]],[56,[[73,[45]]]],[57,[[73,[45]]]],[58,[[73,[44]]]],[59,[[73,[44]]]],[60,[[73,[45]]]],[61,[[73,[45]]]],[62,[[73,[44]]]],[63,[[73,[44]]]],[64,[[73,[44]]]],[65,[[73,[44]]]],[66,[[73,[44]]]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[43,43],15],[[44,44],15],[[45,45],15],[[46,46],15],[[38,38],15],[[47,47],15],[[48,48],15],[[51,51],15],[[52,52],15],[[53,53],15],[[54,54],15],[[55,55],15],[[56,56],15],[[57,57],15],[[58,58],15],[[59,59],15],[[60,60],15],[[63,63],15],[[64,64],15],[[65,65],15],[[66,66],15],[[67,67],15],[74,[[12,[[12,[17,28]],36]]]],[74,[[12,[[12,[17,28]],36]]]],[[43,30,30,33,3],[[12,[2,36]]]],[[43,30,30,33,3],[[12,[2,36]]]],[[44,30,33,3],[[12,[2,36]]]],[[44,30,33,3],[[12,[2,36]]]],[[45,30,30,33,3],[[12,[2,36]]]],[[45,30,30,33,3],[[12,[2,36]]]],[[46,30,30,30,33,3],[[12,[2,36]]]],[[46,30,30,30,33,3],[[12,[2,36]]]],[[47,30,30,33,3],[[12,[2,36]]]],[[50,30,30,33,3],[[12,[2,36]]]],[[74,33,3],[[12,[2,36]]]],[[35,33,3],[[12,[2,36]]]],[[30,33,3],[[12,[2,36]]]],[[68,33,3],[[12,[2,36]]]],[[69,33,3],[[12,[2,36]]]],[[70,33,3],[[12,[2,36]]]],[[71,33,3],[[12,[2,36]]]],[[43,34,34,33,3],[[12,[2,36]]]],[[44,34,33,3],[[12,[2,36]]]],[[45,34,34,33,3],[[12,[2,36]]]],[[46,34,34,34,33,3],[[12,[2,36]]]],[[47,34,34,33,3],[[12,[2,36]]]],[[48,34,33,3],[[12,[2,36]]]],[[49,34,34,33,3],[[12,[2,36]]]],[[50,34,34,33,3],[[12,[2,36]]]],[[51,34,34,33,3],[[12,[2,36]]]],[[52,34,34,33,3],[[12,[2,36]]]],[[53,34,34,33,3],[[12,[2,36]]]],[[54,34,33,3],[[12,[2,36]]]],[[55,34,34,33,3],[[12,[2,36]]]],[[56,34,34,33,3],[[12,[2,36]]]],[[57,34,34,33,3],[[12,[2,36]]]],[[58,34,33,3],[[12,[2,36]]]],[[59,34,33,3],[[12,[2,36]]]],[[60,34,34,33,3],[[12,[2,36]]]],[[61,34,34,33,3],[[12,[2,36]]]],[[62,34,33,3],[[12,[2,36]]]],[[63,34,33,3],[[12,[2,36]]]],[[64,34,33,3],[[12,[2,36]]]],[[65,34,33,3],[[12,[2,36]]]],[[66,34,33,3],[[12,[2,36]]]],[[34,14],6],[[25,34,33,3],[[12,[2,36]]]],[[37,30,34,33],[[12,[2,36]]]],[[],33],[[],67],[[33,[21,[[2,[4,34]]]]],2],[[33,-1,67,34],[[12,[27,36]]],22],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[30,30],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[[30,-1],30,[[32,[30]]]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[-1,[[12,[38]]],19],[-1,[[12,[35]]],19],[-1,[[12,[31]]],19],[-1,[[12,[30]]],19],[-1,[[12,[37]]],19],[-1,[[12,[68]]],19],[-1,[[12,[69]]],19],[-1,[[12,[70]]],19],[-1,[[12,[71]]],19],[-1,[[12,[72]]],19],[-1,[[12,[67]]],19],[-1,[[12,[34]]],19],[[43,30,30],4],[[43,30,30],4],[[44,30],4],[[44,30],4],[[45,30,30],4],[[45,30,30],4],[[46,30,30,30],4],[[46,30,30,30],4],[[25,34,33,3],[[12,[2,36]]]],[[30,-1],30,[[32,[30]]]],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[[43,43],6],[[44,44],6],[[45,45],6],[[46,46],6],[[38,38],6],[[35,35],6],[[31,31],6],[[30,30],6],[[30,-1],30,[[32,[30]]]],[[47,47],6],[[48,48],6],[[51,51],6],[[52,52],6],[[53,53],6],[[54,54],6],[[55,55],6],[[56,56],6],[[57,57],6],[[58,58],6],[[59,59],6],[[60,60],6],[[63,63],6],[[64,64],6],[[65,65],6],[[66,66],6],[[37,37],6],[[68,68],6],[[69,69],6],[[70,70],6],[[71,71],6],[[72,72],6],[[67,67],6],[[34,34],6],[[34,34,33],[[12,[6,36]]]],[[43,35,35,33],[[12,[35,36]]]],[[44,35,33],[[12,[35,36]]]],[[45,35,35,33],[[12,[35,36]]]],[[46,35,35,35,33],[[12,[35,36]]]],[[35,33],[[12,[35,36]]]],[[47,35,35,33],[[12,[35,36]]]],[[48,35,33],[[12,[35,36]]]],[[49,35,35,33],[[12,[35,36]]]],[[50,35,35,33],[[12,[35,36]]]],[[51,35,35,33],[[12,[35,36]]]],[[52,35,35,33],[[12,[35,36]]]],[[53,35,35,33],[[12,[35,36]]]],[[54,35,33],[[12,[35,36]]]],[[55,35,35,33],[[12,[35,36]]]],[[56,35,35,33],[[12,[35,36]]]],[[57,35,35,33],[[12,[35,36]]]],[[58,35,33],[[12,[35,36]]]],[[59,35,33],[[12,[35,36]]]],[[60,35,35,33],[[12,[35,36]]]],[[61,35,35,33],[[12,[35,36]]]],[[62,35,33],[[12,[35,36]]]],[[63,35,33],[[12,[35,36]]]],[[64,35,33],[[12,[35,36]]]],[[65,35,33],[[12,[35,36]]]],[[66,35,33],[[12,[35,36]]]],[[35,35],35],[[30,35],30],[41,37],[[38,7],8],[[33,7],8],[[33,7],8],[[36,7],8],[[36,7],8],[[35,7],8],[[35,7],8],[[31,7],8],[[31,7],8],[[30,7],8],[[30,7],8],[[47,7],8],[[47,7],8],[[48,7],8],[[48,7],8],[[49,7],8],[[49,7],8],[[50,7],8],[[50,7],8],[[51,7],8],[[51,7],8],[[52,7],8],[[52,7],8],[[53,7],8],[[53,7],8],[[54,7],8],[[54,7],8],[[55,7],8],[[55,7],8],[[56,7],8],[[56,7],8],[[57,7],8],[[57,7],8],[[58,7],8],[[58,7],8],[[59,7],8],[[59,7],8],[[60,7],8],[[60,7],8],[[61,7],8],[[61,7],8],[[62,7],8],[[62,7],8],[[63,7],8],[[63,7],8],[[64,7],8],[[64,7],8],[[65,7],8],[[65,7],8],[[66,7],8],[[66,7],8],[[37,7],8],[[37,7],8],[[68,7],8],[[68,7],8],[[69,7],8],[[69,7],8],[[70,7],8],[[70,7],8],[[71,7],8],[[71,7],8],[[72,7],8],[[72,7],8],[[67,7],8],[[67,7],8],[[34,7],8],[[34,7],8],[-1,-1,[]],[75,38],[-1,-1,[]],[-1,-1,[]],[1,36],[-1,-1,[]],[[[2,[14,67,34,30]]],31],[[[2,[14,34]]],31],[[[2,[4,72]]],31],[[[2,[14,67,[13,[34]],30]]],31],[[[2,[14,71]]],31],[[[2,[4,70]]],31],[[[2,[4,34]]],31],[[[2,[14,35]]],31],[[[2,[37,30]]],31],[[[2,[4,67,34,30]]],31],[[[73,[31]]],31],[[[2,[14,67,30]]],31],[-1,-1,[]],[[[2,[4,35]]],31],[[[2,[14,72]]],31],[[[2,[4,71]]],31],[[[2,[14,30]]],31],[[[2,[4,30]]],31],[[[21,[-1]]],31,[[32,[31]]]],[[[2,[14,70]]],31],[[[2,[4,67,[13,[34]],30]]],31],[[[2,[4,67,30]]],31],[[[76,[-1,-2]]],31,[],[]],[35,30],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[6,67],[-1,-1,[]],[-1,-1,[]],[[71,[21,[4]]],72],[[30,-1],30,[[32,[30]]]],[[33,34],[[21,[[2,[4,35]]]]]],[71,[[39,[[2,[4,67,34]]]]]],[[33,34,14],[[13,[[2,[35,34]]]]]],[[37,30,34,33],[[12,[[77,[4,[2,[67,34]]]],36]]]],[71,30],[[37,30,30,33],[[12,[34,36]]]],[71,[[13,[14]]]],[71,14],[[30,33],[[12,[[13,[67]],36]]]],[[34,34,[77,[4,34]],[78,[4]],33],[[12,[2,36]]]],[72,14],[71,34],[[34,33],[[13,[67]]]],[[79,33],[[12,[5,36]]]],[[79,33],[[12,[5,36]]]],[[79,33,5],[[12,[5,36]]]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[34,33,5],[[12,[5,36]]]],[[34,33],[[21,[4]]]],[[80,33],[[12,[34,36]]]],[[80,33],[[12,[34,36]]]],[[80,33,5],[[12,[34,36]]]],[[35,33,5],[[12,[34,36]]]],[[30,33,5],[[12,[34,36]]]],[[68,33,5],[[12,[34,36]]]],[[69,33,5],[[12,[34,36]]]],[[70,33,5],[[12,[34,36]]]],[[71,33,5],[[12,[34,36]]]],[[72,33,5],[[12,[34,36]]]],[[33,34,14],[[13,[34]]]],[[30,-1],30,[[32,[30]]]],[[30,-1],30,[[32,[31]]]],[[33,34,14],6],[[34,34,33],[[12,[6,36]]]],[38,6],[[38,-1],2,20],[[35,-1],2,20],[[31,-1],2,20],[[30,-1],2,20],[[47,-1],2,20],[[48,-1],2,20],[[51,-1],2,20],[[52,-1],2,20],[[53,-1],2,20],[[54,-1],2,20],[[55,-1],2,20],[[56,-1],2,20],[[57,-1],2,20],[[58,-1],2,20],[[59,-1],2,20],[[60,-1],2,20],[[63,-1],2,20],[[64,-1],2,20],[[65,-1],2,20],[[66,-1],2,20],[[37,-1],2,20],[[68,-1],2,20],[[69,-1],2,20],[[70,-1],2,20],[[71,-1],2,20],[[72,-1],2,20],[[67,-1],2,20],[[34,-1],2,20],[[30,-1],30,[[32,[30]]]],[[37,30,30,30,33],[[12,[30,36]]]],[[30,-1,-2],30,[[32,[30]]],[[32,[30]]]],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[42,37],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[34,6],[38,6],[34,6],[67,6],[38,6],[[37,30,34,33],[[12,[6,36]]]],[38,6],[[30,33],[[12,[6,36]]]],[[34,34,33],[[12,[6,36]]]],[67,6],[38,6],[34,6],[[34,33],[[12,[6,36]]]],[[34,[78,[4]],33],[[12,[6,36]]]],[[34,33],[[12,[6,36]]]],[34,6],[38,6],[[30,-1],30,[[32,[30]]]],[[14,34,34],34],[[-1,35,-2],30,22,[[32,[30]]]],[[[21,[[2,[14,35]]]],-1],30,[[32,[30]]]],[[-1,71,-2],30,22,[[32,[30]]]],[[[76,[14,71]],-1],30,[[32,[30]]]],[[-1,34,-2],30,22,[[32,[30]]]],[[[21,[[2,[14,34]]]],-1],30,[[32,[30]]]],[[-1,-2,[13,[34]],-3,-4],30,22,[[32,[67]]],[[32,[30]]],[[32,[30]]]],[[[21,[[2,[14,67,[13,[34]],30]]]],-1],30,[[32,[30]]]],[38,[[13,[75]]]],[[30,-1],30,[[32,[30]]]],[-1,31,[[32,[[21,[31]]]]]],[[30,[39,[[2,[37,30]]]],33],[[12,[30,36]]]],[[-1,-2],31,22,[[32,[[21,[31]]]]]],[[35,[21,[34]]],35],[[72,[21,[34]],33],[[12,[71,36]]]],[[30,-1],30,[[32,[30]]]],[43,4],[43,4],[44,4],[44,4],[45,4],[45,4],[46,4],[46,4],0,0,[30,30],[[30,-1],30,[[32,[30]]]],[-1,50,45],[[4,[21,[34]],34],70],[[[13,[4]],[21,[[2,[4,67,34]]]],34,-1],71,[[32,[30]]]],[[4,[21,[4]],[21,[[2,[4,67,34]]]],34,-1],72,[[32,[30]]]],[30,30],[[30,-1],30,[[32,[30]]]],[[43,43],[[13,[15]]]],[[44,44],[[13,[15]]]],[[45,45],[[13,[15]]]],[[46,46],[[13,[15]]]],[[38,38],[[13,[15]]]],[[47,47],[[13,[15]]]],[[48,48],[[13,[15]]]],[[51,51],[[13,[15]]]],[[52,52],[[13,[15]]]],[[53,53],[[13,[15]]]],[[54,54],[[13,[15]]]],[[55,55],[[13,[15]]]],[[56,56],[[13,[15]]]],[[57,57],[[13,[15]]]],[[58,58],[[13,[15]]]],[[59,59],[[13,[15]]]],[[60,60],[[13,[15]]]],[[63,63],[[13,[15]]]],[[64,64],[[13,[15]]]],[[65,65],[[13,[15]]]],[[66,66],[[13,[15]]]],[[67,67],[[13,[15]]]],[[34,33,[77,[[2,[34,[21,[34]]]],34]]],[[12,[34,36]]]],[37,37],[[30,-1],30,[[32,[30]]]],[30,30],[30,30],[[[13,[4]],[21,[[2,[4,67,34]]]],34,-1],35,[[32,[30]]]],[[71,3],2],[[30,-1],30,[[32,[67]]]],[[30,-1],30,[[32,[30]]]],0,0,[[43,30,30,33],[[12,[34,36]]]],[[43,30,30,33],[[12,[34,36]]]],[[44,30,33],[[12,[34,36]]]],[[44,30,33],[[12,[34,36]]]],[[45,30,30,33],[[12,[34,36]]]],[[45,30,30,33],[[12,[34,36]]]],[[46,30,30,30,33],[[12,[34,36]]]],[[46,30,30,30,33],[[12,[34,36]]]],[[47,30,30,33],[[12,[34,36]]]],[[48,30,33],[[12,[34,36]]]],[[49,30,30,33],[[12,[34,36]]]],[[50,30,30,33],[[12,[34,36]]]],[[51,30,30,33],[[12,[34,36]]]],[[52,30,30,33],[[12,[34,36]]]],[[53,30,30,33],[[12,[34,36]]]],[[54,30,33],[[12,[34,36]]]],[[55,30,30,33],[[12,[34,36]]]],[[56,30,30,33],[[12,[34,36]]]],[[57,30,30,33],[[12,[34,36]]]],[[58,30,33],[[12,[34,36]]]],[[59,30,33],[[12,[34,36]]]],[[60,30,30,33],[[12,[34,36]]]],[[61,30,30,33],[[12,[34,36]]]],[[62,30,33],[[12,[34,36]]]],[[63,30,33],[[12,[34,36]]]],[[64,30,33],[[12,[34,36]]]],[[65,30,33],[[12,[34,36]]]],[[66,30,33],[[12,[34,36]]]],[[38,-1],12,24],[[35,-1],12,24],[[31,-1],12,24],[[30,-1],12,24],[[37,-1],12,24],[[68,-1],12,24],[[69,-1],12,24],[[70,-1],12,24],[[71,-1],12,24],[[72,-1],12,24],[[67,-1],12,24],[[34,-1],12,24],[[71,-1],2,22],[[81,33],[[12,[81,36]]]],[[81,33,5],[[12,[81,36]]]],[[35,33,5],[[12,[35,36]]]],[[34,33,5],[[12,[34,36]]]],[[34,33],[[12,[34,36]]]],[[34,33],[[12,[34,36]]]],[[34,33],[[12,[34,36]]]],[[34,33],[[12,[34,36]]]],[[34,33,34,-1],[[12,[34,36]]],[[83,[34,33],[[82,[[12,[6,36]]]]]]]],[[34,33],[[12,[34,36]]]],[[34,33],[[12,[34,36]]]],[[34,33],[[12,[34,36]]]],[[34,33],[[12,[34,36]]]],[30,30],[[34,33],34],[[[76,[4,37]]],37],[[[76,[14,30]]],30],[[30,-1],30,[[32,[30]]]],[[80,14,34],2],[[35,14,34],2],[[30,14,34],2],[[68,14,34],2],[[69,14,34],2],[[70,14,34],2],[[71,14,34],2],[[72,14,34],2],[[34,14,34],34],[[80,[39,[4]],[39,[34]]],2],[[80,[39,[4]],[39,[34]]],2],[[-1,-2],37,[[32,[67]]],22],[[35,[21,[4]]],35],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[[30,33],[[12,[30,36]]]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[[[21,[37]]],37],[[84,33],[[12,[2,36]]]],[[43,30,30,33],[[12,[2,36]]]],[[43,30,30,33],[[12,[2,36]]]],[[44,30,33],[[12,[2,36]]]],[[44,30,33],[[12,[2,36]]]],[[45,30,30,33],[[12,[2,36]]]],[[45,30,30,33],[[12,[2,36]]]],[[46,30,30,30,33],[[12,[2,36]]]],[[46,30,30,30,33],[[12,[2,36]]]],[[35,33],[[12,[2,36]]]],[[31,33],[[12,[2,36]]]],[[30,33],[[12,[2,36]]]],[[37,30,30,33],[[12,[2,36]]]],[[68,33],[[12,[2,36]]]],[[69,33],[[12,[2,36]]]],[[70,33],[[12,[2,36]]]],[[71,33],[[12,[2,36]]]],[[72,33],[[12,[2,36]]]],[[34,33],[[12,[2,36]]]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[[30,-1],30,22],[-1,35,22],[-1,30,22],[[[39,[4]],4],[[13,[5]]]],[[30,-1],30,[[32,[30]]]],[[],37],[[35,-1],35,[[32,[31]]]],[[30,-1],30,[[32,[31]]]],[[71,-1],71,[[32,[31]]]],[[72,-1],72,[[32,[31]]]],0,0,0,0,0,0,0,0,0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[75,75],[[-1,-2],2,[],[]],[[75,75],15],0,[5,-1,[]],[5,-1,[]],[-1,[[12,[75]]],19],[5,2],[[75,75],6],0,[[75,7],8],[-1,-1,[]],[[75,14],4],[[75,-1],2,20],[[],5],[-1,-2,[],[]],0,0,0,[-1,[[12,[[12,[17,28]],4]]],22],[[-1,[13,[14]]],[[12,[30,4]]],22],[[-1,[13,[14]]],[[12,[30,4]]],22],[-1,[[12,[30,4]]],22],[-1,[[12,[[12,[18,29]],4]]],22],[[75,75],[[13,[15]]]],[[75,-1],12,24],[-1,-2,[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[85,85],[[-1,-2],2,[],[]],[[85,85],15],[5,-1,[]],[5,-1,[]],[-1,[[12,[85]]],19],[5,2],[[85,85],6],[[85,7],8],[[85,7],8],[-1,-1,[]],[[85,-1],2,20],[[],5],0,[-1,-2,[],[]],0,[[4,5,5],85],0,[[85,85],[[13,[15]]]],[[85,-1],12,24],[-1,-2,[],[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],0,0,[[],86],[87,87],[88,88],[89,89],[90,90],[91,91],[92,92],[86,86],[23,23],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[87,87],15],[[88,88],15],[[89,89],15],[[90,90],15],[[91,91],15],[[92,92],15],[[86,86],15],[[23,23],15],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[-1,[[12,[87]]],19],[-1,[[12,[88]]],19],[-1,[[12,[89]]],19],[-1,[[12,[90]]],19],[-1,[[12,[91]]],19],[-1,[[12,[92]]],19],[-1,[[12,[86]]],19],[-1,[[12,[23]]],19],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[[87,87],6],[[88,88],6],[[89,89],6],[[90,90],6],[[91,91],6],[[92,92],6],[[86,86],6],[[23,23],6],[[87,7],8],[[87,7],8],[[88,7],8],[[88,7],8],[[89,7],8],[[89,7],8],[[90,7],8],[[90,7],8],[[91,7],8],[[91,7],8],[[92,7],8],[[92,7],8],[[86,7],8],[[86,7],8],[[23,7],8],[[23,7],8],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[[87,-1],2,20],[[88,-1],2,20],[[89,-1],2,20],[[90,-1],2,20],[[91,-1],2,20],[[92,-1],2,20],[[86,-1],2,20],[[23,-1],2,20],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],0,0,[[90,5],86],[[91,5],23],[[87,87],[[13,[15]]]],[[88,88],[[13,[15]]]],[[89,89],[[13,[15]]]],[[90,90],[[13,[15]]]],[[91,91],[[13,[15]]]],[[92,92],[[13,[15]]]],[[86,86],[[13,[15]]]],[[23,23],[[13,[15]]]],[[],86],[[87,-1],12,24],[[88,-1],12,24],[[89,-1],12,24],[[90,-1],12,24],[[91,-1],12,24],[[92,-1],12,24],[[86,-1],12,24],[[23,-1],12,24],[[],23],[[],23],[[],23],[[],86],[[],86],[[],86],[[],23],[[],23],[[],23],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],0,0,[[93,18],[[12,[4,4]]]],[[93,94,[21,[94]],[21,[5]],5,5],[[12,[4,4]]]],[[93,29],[[12,[4,4]]]],[[93,95,[21,[94]],[21,[5]],5,5],[[12,[4,4]]]],0,[[96,5],4],[[96,94,[13,[5]]],4],[[96,86],[[12,[4,4]]]],[96,[[13,[4]]]],[96,14],[[96,94],4],[96,[[12,[4,4]]]],[96,[[12,[4,4]]]],[[96,[21,[97]]],[[13,[4]]]],[[96,6],[[13,[4]]]],[96,[[13,[4]]]],[[96,[21,[97]]],[[13,[4]]]],[[96,6],[[13,[4]]]],[[96,23],[[12,[4,4]]]],[[96,95],[[12,[4,4]]]],[96,6],[[96,86],6],[[96,23],6],[96,14],0,[-1,-2,[],[]],[-1,-2,[],[]],[[98,5],4],[[],98],[5,-1,[]],[5,-1,[]],[5,2],[[98,94,[13,[5]]],4],[-1,-1,[]],[[98,86],[[12,[4,4]]]],[[],5],[-1,-2,[],[]],[98,14],[[98,94],4],[98,[[12,[4,4]]]],[98,[[12,[4,4]]]],[[98,[21,[97]]],[[13,[4]]]],[[98,6],[[13,[4]]]],[98,[[13,[4]]]],[[98,6],[[13,[4]]]],[[98,23],[[12,[4,4]]]],[[98,95],[[12,[4,4]]]],[98,6],[[98,86],6],[[98,23],6],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],[98,14],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[99,85],2],[42,41],[41,42],[100,2],[100,2],[100,2],[100,2],[100,2],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[100,2],[18,18],[94,94],[29,29],[95,95],[99,99],[9,9],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[18,18],15],[[94,94],15],[100,[[12,[18,29]]]],[18,[[12,[18,29]]]],[29,[[12,[18,29]]]],[[100,14],2],[[],[[101,[99]]]],[[],[[102,[99]]]],[[],18],[[],29],[[],103],[[],99],[5,-1,[]],[5,-1,[]],[100,2],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[100,2],[[18,18],6],[[94,94],6],[[29,29],6],[[95,95],6],[[9,9],6],0,[[104,85,[13,[[21,[42]]]]],[[12,[2,4]]]],[[100,85],[[12,[2,9]]]],[[103,85,[13,[[21,[42]]]]],[[12,[2,4]]]],[[99,85,[13,[[21,[42]]]]],[[12,[2,4]]]],0,[18,18],[29,29],[[18,7],8],[[94,7],8],[[94,7],8],[[29,7],8],[[95,7],8],[[95,7],8],[[103,7],8],[[99,7],8],[[9,7],8],[[9,7],8],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[18,29],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[[104,86],[[12,[42,4]]]],[[100,86],2],[[103,86],[[12,[42,4]]]],[[99,86],[[12,[42,4]]]],[18,[[77,[97,[21,[94]]]]]],[29,[[77,[97,[21,[95]]]]]],[18,[[21,[94]]]],[29,[[21,[95]]]],[18,[[2,[[21,[94]],[77,[97,[21,[94]]]]]]]],[29,[[2,[[21,[95]],[77,[97,[21,[95]]]]]]]],[[18,-1],2,20],[[94,-1],2,20],[100,2],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],0,[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[100,2],[[100,5],2],[[100,27],2],[-1,[[101,[-1]]],104],[-1,[[102,[-1]]],104],[-1,103,22],[[[21,[42]]],103],[[100,94],2],[[18,94],2],[[29,94],2],0,[103,4],[103,[[21,[42]]]],[[18,18],[[13,[15]]]],[[94,94],[[13,[15]]]],[[29,29],[[13,[15]]]],[[95,95],[[13,[15]]]],[[9,9],[[13,[15]]]],[104,[[12,[42,4]]]],[100,[[12,[2,9]]]],[103,[[12,[42,4]]]],[99,[[12,[42,4]]]],[[104,42],[[12,[2,4]]]],[100,[[12,[2,9]]]],[[103,42],[[12,[2,4]]]],[[99,42],[[12,[2,4]]]],[[104,42,23],[[12,[2,4]]]],[[100,23],2],[[103,42,23],[[12,[2,4]]]],[[99,42,23],[[12,[2,4]]]],[100,2],[100,2],[100,2],[[[101,[-1]],18],[[12,[-1,4]]],104],[[[102,[-1]],29],[[12,[-1,4]]],104],[100,2],[[100,41],[[12,[2,9]]]],[[100,[21,[41]]],[[12,[2,9]]]],[[100,42],2],[[100,[21,[42]]],2],[[100,95],[[12,[2,9]]]],[[18,95],[[12,[2,9]]]],[[29,95],[[12,[2,9]]]],[[100,5],2],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[100,2]],"c":[],"p":[[6,"Error",10],[1,"tuple"],[10,"AssemblyProgram",10],[5,"String",2640],[1,"usize"],[1,"bool"],[5,"Formatter",2641],[8,"Result",2641],[6,"Error",2336],[6,"CoreOp",65],[6,"StandardOp",416],[6,"Result",2642],[6,"Option",2643],[1,"str"],[6,"Ordering",2644],[5,"TypeId",2645],[5,"CoreProgram",65],[5,"CoreProgram",2336],[10,"Deserializer",2646],[10,"Hasher",2647],[5,"Vec",2648],[10,"ToString",2640],[5,"Output",1974],[10,"Serializer",2649],[6,"Location",376],[5,"Globals",348],[1,"isize"],[5,"StandardProgram",416],[5,"StandardProgram",2336],[6,"Expr",566],[6,"Declaration",566],[10,"Into",2650],[5,"Env",566],[6,"Type",566],[6,"ConstExpr",566],[6,"Error",566],[6,"Pattern",566],[6,"Annotation",566],[1,"slice"],[1,"char"],[1,"f64"],[1,"i64"],[10,"AssignOp",566],[10,"UnaryOp",566],[10,"BinaryOp",566],[10,"TernaryOp",566],[5,"Add",566],[5,"Negate",566],[6,"Arithmetic",566],[5,"Assign",566],[5,"BitwiseAnd",566],[5,"BitwiseNand",566],[5,"BitwiseNor",566],[5,"BitwiseNot",566],[5,"BitwiseOr",566],[5,"BitwiseXor",566],[6,"Comparison",566],[5,"Get",566],[6,"Put",566],[5,"And",566],[5,"Or",566],[5,"Not",566],[5,"New",566],[5,"Delete",566],[5,"Tag",566],[5,"Data",566],[6,"Mutability",566],[5,"CoreBuiltin",566],[5,"StandardBuiltin",566],[5,"FFIProcedure",566],[5,"Procedure",566],[5,"PolyProcedure",566],[5,"Box",2651],[10,"Compile",566],[5,"SourceCodeLocation",1911],[5,"BTreeMap",2652],[5,"HashMap",2653],[5,"HashSet",2654],[10,"GetSize",566],[10,"GetType",566],[10,"Simplify",566],[17,"Output"],[10,"Fn",2655],[10,"TypeCheck",566],[5,"FFIBinding",1946],[5,"Input",1974],[6,"Axis",1974],[6,"Direction",1974],[6,"Color",1974],[6,"InputMode",1974],[6,"OutputMode",1974],[5,"Channel",1974],[10,"CompiledTarget",2280],[6,"CoreOp",2336],[6,"StandardOp",2336],[10,"Architecture",2280],[1,"i32"],[5,"C",2306],[5,"StandardDevice",2336],[10,"VirtualMachineProgram",2336],[5,"CoreInterpreter",2336],[5,"StandardInterpreter",2336],[5,"TestingDevice",2336],[10,"Device",2336],[15,"Compare",207],[15,"IsGreater",207],[15,"IsGreaterEqual",207],[15,"IsLess",207],[15,"IsLessEqual",207],[15,"IsEqual",207],[15,"IsNotEqual",207],[15,"GetAddress",207],[15,"Move",207],[15,"Copy",207],[15,"Index",207],[15,"Add",207],[15,"Sub",207],[15,"Mul",207],[15,"Div",207],[15,"Rem",207],[15,"DivRem",207],[15,"VecAdd",207],[15,"VecSub",207],[15,"VecMul",207],[15,"VecDiv",207],[15,"VecRem",207],[15,"And",207],[15,"Or",207],[15,"VecNot",207],[15,"VecAnd",207],[15,"VecOr",207],[15,"VecInc",207],[15,"VecDec",207],[15,"LeftShift",207],[15,"LogicalRightShift",207],[15,"ArithmeticRightShift",207],[15,"VecLeftShift",207],[15,"VecLogicalRightShift",207],[15,"VecArithmeticRightShift",207],[15,"VecGez",207],[15,"VecNeg",207],[15,"VecOffset",207],[15,"VecIndex",207],[15,"PopFrom",207],[15,"Array",207],[15,"Const",207],[15,"BitwiseNand",207],[15,"BitwiseXor",207],[15,"BitwiseOr",207],[15,"BitwiseNor",207],[15,"BitwiseAnd",207],[15,"VecBitwiseAnd",207],[15,"VecBitwiseOr",207],[15,"VecBitwiseXor",207],[15,"VecBitwiseNor",207],[15,"VecBitwiseNand",207],[15,"VecBitwiseNot",207],[15,"Global",207],[15,"PushTo",207],[15,"IsGreater",510],[15,"IsLess",510],[15,"Const",510],[15,"Pow",510],[15,"Add",510],[15,"Sub",510],[15,"Mul",510],[15,"Div",510],[15,"Rem",510],[15,"VecAdd",510],[15,"VecSub",510],[15,"VecMul",510],[15,"VecDiv",510],[15,"VecRem",510],[15,"VecNeg",510],[15,"VecPow",510],[15,"VecSin",510],[15,"VecCos",510],[15,"VecTan",510],[15,"VecASin",510],[15,"VecACos",510],[15,"VecATan",510],[15,"VecGez",510],[15,"FromImport",1901],[15,"MismatchedTypes",1903],[15,"MismatchedMutability",1903],[15,"NonExhaustivePatterns",1903]],"b":[[45,"impl-Display-for-Error"],[46,"impl-Debug-for-Error"],[173,"impl-Display-for-CoreProgram"],[174,"impl-Debug-for-CoreProgram"],[175,"impl-Debug-for-CoreOp"],[176,"impl-Display-for-CoreOp"],[359,"impl-Display-for-Globals"],[360,"impl-Debug-for-Globals"],[402,"impl-Debug-for-Location"],[403,"impl-Display-for-Location"],[480,"impl-Display-for-StandardProgram"],[481,"impl-Debug-for-StandardProgram"],[482,"impl-Debug-for-StandardOp"],[483,"impl-Display-for-StandardOp"],[1218,"impl-PartialEq-for-Expr"],[1219,"impl-Expr"],[1274,"impl-Display-for-Env"],[1275,"impl-Debug-for-Env"],[1276,"impl-Display-for-Error"],[1277,"impl-Debug-for-Error"],[1278,"impl-Display-for-ConstExpr"],[1279,"impl-Debug-for-ConstExpr"],[1280,"impl-Debug-for-Declaration"],[1281,"impl-Display-for-Declaration"],[1282,"impl-Display-for-Expr"],[1283,"impl-Debug-for-Expr"],[1284,"impl-Debug-for-Add"],[1285,"impl-Display-for-Add"],[1286,"impl-Debug-for-Negate"],[1287,"impl-Display-for-Negate"],[1288,"impl-Debug-for-Arithmetic"],[1289,"impl-Display-for-Arithmetic"],[1290,"impl-Debug-for-Assign"],[1291,"impl-Display-for-Assign"],[1292,"impl-Display-for-BitwiseAnd"],[1293,"impl-Debug-for-BitwiseAnd"],[1294,"impl-Debug-for-BitwiseNand"],[1295,"impl-Display-for-BitwiseNand"],[1296,"impl-Debug-for-BitwiseNor"],[1297,"impl-Display-for-BitwiseNor"],[1298,"impl-Debug-for-BitwiseNot"],[1299,"impl-Display-for-BitwiseNot"],[1300,"impl-Debug-for-BitwiseOr"],[1301,"impl-Display-for-BitwiseOr"],[1302,"impl-Debug-for-BitwiseXor"],[1303,"impl-Display-for-BitwiseXor"],[1304,"impl-Debug-for-Comparison"],[1305,"impl-Display-for-Comparison"],[1306,"impl-Display-for-Get"],[1307,"impl-Debug-for-Get"],[1308,"impl-Debug-for-Put"],[1309,"impl-Display-for-Put"],[1310,"impl-Debug-for-And"],[1311,"impl-Display-for-And"],[1312,"impl-Debug-for-Or"],[1313,"impl-Display-for-Or"],[1314,"impl-Display-for-Not"],[1315,"impl-Debug-for-Not"],[1316,"impl-Debug-for-New"],[1317,"impl-Display-for-New"],[1318,"impl-Display-for-Delete"],[1319,"impl-Debug-for-Delete"],[1320,"impl-Debug-for-Tag"],[1321,"impl-Display-for-Tag"],[1322,"impl-Debug-for-Data"],[1323,"impl-Display-for-Data"],[1324,"impl-Debug-for-Pattern"],[1325,"impl-Display-for-Pattern"],[1326,"impl-Display-for-CoreBuiltin"],[1327,"impl-Debug-for-CoreBuiltin"],[1328,"impl-Debug-for-StandardBuiltin"],[1329,"impl-Display-for-StandardBuiltin"],[1330,"impl-Debug-for-FFIProcedure"],[1331,"impl-Display-for-FFIProcedure"],[1332,"impl-Display-for-Procedure"],[1333,"impl-Debug-for-Procedure"],[1334,"impl-Debug-for-PolyProcedure"],[1335,"impl-Display-for-PolyProcedure"],[1336,"impl-Display-for-Mutability"],[1337,"impl-Debug-for-Mutability"],[1338,"impl-Debug-for-Type"],[1339,"impl-Display-for-Type"],[1346,"impl-From%3C(%26str,+Mutability,+Type,+Expr)%3E-for-Declaration"],[1347,"impl-From%3C(%26str,+Type)%3E-for-Declaration"],[1348,"impl-From%3C(String,+PolyProcedure)%3E-for-Declaration"],[1349,"impl-From%3C(%26str,+Mutability,+Option%3CType%3E,+Expr)%3E-for-Declaration"],[1350,"impl-From%3C(%26str,+Procedure)%3E-for-Declaration"],[1351,"impl-From%3C(String,+FFIProcedure)%3E-for-Declaration"],[1352,"impl-From%3C(String,+Type)%3E-for-Declaration"],[1353,"impl-From%3C(%26str,+ConstExpr)%3E-for-Declaration"],[1354,"impl-From%3C(Pattern,+Expr)%3E-for-Declaration"],[1355,"impl-From%3C(String,+Mutability,+Type,+Expr)%3E-for-Declaration"],[1356,"impl-From%3CBox%3CDeclaration%3E%3E-for-Declaration"],[1357,"impl-From%3C(%26str,+Mutability,+Expr)%3E-for-Declaration"],[1359,"impl-From%3C(String,+ConstExpr)%3E-for-Declaration"],[1360,"impl-From%3C(%26str,+PolyProcedure)%3E-for-Declaration"],[1361,"impl-From%3C(String,+Procedure)%3E-for-Declaration"],[1362,"impl-From%3C(%26str,+Expr)%3E-for-Declaration"],[1363,"impl-From%3C(String,+Expr)%3E-for-Declaration"],[1364,"impl-From%3CVec%3CT%3E%3E-for-Declaration"],[1365,"impl-From%3C(%26str,+FFIProcedure)%3E-for-Declaration"],[1366,"impl-From%3C(String,+Mutability,+Option%3CType%3E,+Expr)%3E-for-Declaration"],[1367,"impl-From%3C(String,+Mutability,+Expr)%3E-for-Declaration"],[1368,"impl-From%3CBTreeMap%3CK,+V%3E%3E-for-Declaration"],[1957,"impl-Display-for-FFIBinding"],[1958,"impl-Debug-for-FFIBinding"],[2162,"impl-Debug-for-Axis"],[2163,"impl-Display-for-Axis"],[2164,"impl-Debug-for-Direction"],[2165,"impl-Display-for-Direction"],[2166,"impl-Debug-for-Color"],[2167,"impl-Display-for-Color"],[2168,"impl-Debug-for-InputMode"],[2169,"impl-Display-for-InputMode"],[2170,"impl-Debug-for-OutputMode"],[2171,"impl-Display-for-OutputMode"],[2172,"impl-Display-for-Channel"],[2173,"impl-Debug-for-Channel"],[2174,"impl-Debug-for-Input"],[2175,"impl-Display-for-Input"],[2176,"impl-Display-for-Output"],[2177,"impl-Debug-for-Output"],[2506,"impl-Display-for-CoreOp"],[2507,"impl-Debug-for-CoreOp"],[2509,"impl-Debug-for-StandardOp"],[2510,"impl-Display-for-StandardOp"],[2513,"impl-Debug-for-Error"],[2514,"impl-Display-for-Error"]]}]\ +["sage",{"doc":"The Sage Programming Language","t":"SSSCCCCCCCEKEEEEEEGEEEEEEEEEPPPPPPNNNNNCMNNNNNNNNMCNNMCNMNCMNNNNNPPPPPPPPPPPPPPPPGFPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPNNNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOFNNNNNNNNNNNNNNNNNNNNNNNNNNNSPSSSSSSSPPGPSSNNNNNNNNNNNNNNNNNNNNNNNNNPPPPPPPPPPPPPPPPPPPPPGFPPPPPPPPPPPPPPPPPPPNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOHFPPFPPPGPPPPPPPGPPPPPPFKPKPFFFFFFPPTTPPPPGKPPPGPPPPFPPTFPPGPPFPPPPPPPPPPFPGGPFPPPPPFKKPPPPPPPPPPPPPPPPPPPPPPPPPPTPPPPPPPPPPPPPPPPGPTFPPFPPPPPPFPPPFGPPPPPFPPPPFGPPPPPTKPPPFPPPPPPPPPPPTFPPKPPPPPGPPPKPPPTKPPPPPPPPPPPPPPPPPNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOOOOOOOFNNNNNONNNNNONNNNNNOOOHHHHHNNNNNNCCFNNNNNNNNNNNNNNNONONONNNNNNNPPPPGPPPPPPPPPPFPPGPPPPPPPPPPGPPPPPPPPFGPPPPPPPPPPPPPPFGPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNKKNNNNCMMMNMMMMNNNNNMMMMMMFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNPPPPPPPPPPPPPPPPFGPFPPPKPPPPGPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPFFGFPPPPPFPPPKPPNHHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOMNNNONNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNMNNONNNNNNNMNNNMNNNMNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","n":["LOGO","LOGO_WITH_COLOR","NULL","asm","frontend","lir","parse","side_effects","targets","vm","A","AssemblyProgram","B","C","CoreOp","CoreProgram","D","E","Error","F","FP","GP","Globals","Location","REGISTERS","SP","StandardOp","StandardProgram","UndefinedGlobal","UndefinedLabel","Unexpected","Unmatched","UnsupportedInstruction","VirtualMachineError","borrow","borrow_mut","clone","clone_into","comment","core","current_instruction","deref","deref_mut","drop","eq","fmt","fmt","from","from","get_op","globals","init","into","is_defined","location","log_instructions_after","op","partial_cmp","std","std_op","to_owned","to_string","try_from","try_into","type_id","Add","And","ArithmeticRightShift","Array","BitwiseAnd","BitwiseNand","BitwiseNor","BitwiseNot","BitwiseOr","BitwiseXor","Call","CallLabel","Comment","Compare","Const","Copy","CoreOp","CoreProgram","Dec","Div","DivRem","Else","End","Fn","Get","GetAddress","Global","If","Inc","Index","IsEqual","IsGreater","IsGreaterEqual","IsLess","IsLessEqual","IsNotEqual","LeftShift","LogicalRightShift","Many","Move","Mul","Neg","Next","Not","Or","Pop","PopFrom","Prev","Push","PushAddress","PushConst","PushTo","Put","Rem","Return","Set","SetLabel","Sub","Swap","VecAdd","VecAnd","VecArithmeticRightShift","VecBitwiseAnd","VecBitwiseNand","VecBitwiseNor","VecBitwiseNot","VecBitwiseOr","VecBitwiseXor","VecDec","VecDiv","VecGez","VecInc","VecIndex","VecLeftShift","VecLogicalRightShift","VecMul","VecNeg","VecNot","VecOffset","VecOr","VecRem","VecSet","VecSub","While","assemble","borrow","borrow","borrow_mut","borrow_mut","clone","clone","clone_into","clone_into","cmp","cmp","code","current_instruction","default","deref","deref","deref_mut","deref_mut","deserialize","deserialize","drop","drop","eq","eq","fmt","fmt","fmt","fmt","from","from","get_op","hash","hash","init","init","into","into","is_defined","new","op","partial_cmp","partial_cmp","push_string","put_string","serialize","serialize","stack_alloc_string","std_op","to_owned","to_owned","to_string","to_string","try_from","try_from","try_into","try_into","type_id","type_id","a","a","a","a","a","a","a","addr","b","b","b","b","b","b","b","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","name","offset","offset","offset","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","size","sp","sp","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","src","vals","vals","Globals","add_global","borrow","borrow_mut","clone","clone_into","default","deref","deref_mut","deserialize","drop","fmt","fmt","from","get_global","get_global_location","get_global_size","get_size","init","into","new","resolve","serialize","to_owned","to_string","try_from","try_into","type_id","A","Address","B","C","D","E","F","FP","GP","Global","Indirect","Location","Offset","REGISTERS","SP","borrow","borrow_mut","clone","clone_into","cmp","deref","deref","deref_mut","deserialize","drop","eq","fmt","fmt","from","hash","init","into","offset","partial_cmp","serialize","to_owned","to_string","try_from","try_into","type_id","ACos","ASin","ATan","Add","Alloc","Call","Const","CoreOp","Cos","Div","Free","IsGreater","IsLess","Mul","Neg","Pow","PushConst","Rem","Set","Sin","Sqrt","StandardOp","StandardProgram","Sub","Tan","ToFloat","ToInt","VecACos","VecASin","VecATan","VecAdd","VecCos","VecDiv","VecGez","VecMul","VecNeg","VecPow","VecRem","VecSet","VecSin","VecSub","VecTan","assemble","borrow","borrow","borrow_mut","borrow_mut","clone","clone","clone_into","clone_into","code","current_instruction","default","deref","deref","deref_mut","deref_mut","deserialize","deserialize","drop","drop","eq","eq","fmt","fmt","fmt","fmt","from","from","from","get_op","init","init","into","into","is_defined","new","op","partial_cmp","partial_cmp","serialize","serialize","std_op","to_owned","to_owned","to_string","to_string","try_from","try_from","try_into","try_into","type_id","type_id","a","a","b","b","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","dst","size","size","size","size","size","size","size","size","size","size","size","size","size","size","src","src","src","src","src","src","src","src","src","src","src","src","src","vals","parse","Add","Add","Alt","And","Annotated","Annotated","Annotated","Annotation","Any","Any","Any","Apply","Apply","ApplyNonProc","ApplyNonTemplate","Arithmetic","Array","Array","Array","As","As","AssemblyError","Assign","AssignOp","AssignOp","BinaryOp","BinaryOp","BitwiseAnd","BitwiseNand","BitwiseNor","BitwiseNot","BitwiseOr","BitwiseXor","Bool","Bool","COMPILER_GENERATED","CONSTANT","Cell","Cell","Char","Char","Comparison","Compile","CompilePolyProc","CompilerGenerated","Const","ConstExpr","ConstExpr","ConstExpr","ConstParam","Constant","CoreBuiltin","CoreBuiltin","CouldntSimplify","DEAD_CODE","Data","DeadCode","Debug","Declaration","Declare","Declare","Delete","Deref","DerefMut","DerefNonPointer","Display","Divide","DuplicateMember","Enum","EnumUnion","EnumUnion","EnumUnion","Env","Equal","Error","Expr","ExternProc","FFIProcedure","FFIProcedure","Float","Float","FromImport","FromImportAll","Get","GetSize","GetType","GreaterThan","GreaterThanOrEqual","If","IfLet","Immutable","Impl","Index","Int","Int","InvalidAs","InvalidAssignOp","InvalidAssignOpTypes","InvalidBinaryOp","InvalidBinaryOpTypes","InvalidConstExpr","InvalidIndex","InvalidMatchExpr","InvalidMonomorphize","InvalidPatternForExpr","InvalidPatternForType","InvalidRefer","InvalidTemplateArgs","InvalidTernaryOp","InvalidTernaryOpTypes","InvalidUnaryOp","InvalidUnaryOpTypes","LIVE_CODE","LessThan","LessThanOrEqual","Let","Location","Many","Many","Many","Match","Member","Member","MemberNotFound","MismatchedMutability","MismatchedTypes","Module","Monomorphize","Multiply","Mutability","Mutable","NONE","Negate","NegativeArrayLength","Never","New","NonExhaustivePatterns","NonIntegralConst","NonSymbol","None","None","None","Not","NotEqual","Null","Of","Or","Pattern","Pointer","Pointer","Poly","PolyProc","PolyProc","PolyProcedure","Power","Proc","Proc","Proc","Procedure","Put","RecursionDepthConst","RecursionDepthTypeEquality","Refer","Remainder","Return","SIMPLIFY_RECURSION_LIMIT","Simplify","SizeOfExpr","SizeOfTemplate","SizeOfType","StandardBuiltin","StandardBuiltin","StaticVar","Struct","Struct","Struct","Struct","Subtract","Symbol","Symbol","Symbol","SymbolNotDefined","TEMPORARY","Tag","Template","Temporary","TernaryOp","TernaryOp","Tuple","Tuple","Tuple","Tuple","Type","Type","Type","Type","TypeCheck","TypeNotDefined","TypeOf","TypeRedefined","USER_GENERATED","UnaryOp","UnaryOp","UnexpectedConstParam","UnimplementedOperator","Union","Union","Union","Unit","UnsizedType","UnsupportedOperation","UnusedExpr","Var","VarPat","Variant","VariantNotFound","When","While","Wildcard","add","add","add_assign","add_associated_const","add_monomorphized_associated_consts","alt","and","annotate","annotate","annotate","app","app","apply","are_patterns_exhaustive","args","args","as_bool","as_char","as_float","as_int","as_symbol","as_type","as_type","assign","assign_op","bitand","bitnand","bitnor","bitnot","bitor","bitor","bitor_assign","bitxor","body","body","bool","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_apply_exprs","can_cast_to","can_decay_to","can_decay_to","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_box","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","compile","compile","compile","compile","compile","compile","compile","compile","compile","compile","compile","compile","compile","compile_expr","compile_expr","compile_expr","compile_expr","compile_expr","compile_expr","compile_expr","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","compile_types","contains_symbol","debug","declare_let_bind","default","default","define_types","define_var","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","display","display","display","display","display","display","display","display","display","div","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","eq","equals","equals","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","eval","field","field","float","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_mono","ge","get_all_associated_consts","get_args","get_associated_const","get_bindings","get_body","get_branch_result_type","get_common_name","get_mangled_name","get_method_call_mutability","get_monomorph_template_args","get_name","get_ret","get_self_param_mutability","get_size","get_size","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_size_checked","get_template_params","get_type","get_type","get_type_checked","get_type_checked","get_type_checked","get_type_checked","get_type_checked","get_type_checked","get_type_checked","get_type_checked","get_type_of_associated_const","get_type_params","gt","hard_with","has_associated_const","has_element_type","has_location","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","hash","idx","if_let_pattern","if_then","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","init","int","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","into","is_atomic","is_compiler_generated","is_concrete","is_const_param","is_constant","is_dead_code","is_exhaustive","is_location","is_method_call","is_monomorph_of","is_mutable","is_none","is_poly","is_recursive","is_recursive_helper","is_self_param_reference","is_simple","is_temporary","le","let_bind","let_const","let_consts","let_proc","let_procs","let_type","let_types","let_var","let_vars","location","lt","many","match_pattern","module","monomorphize","monomorphize","mul","name","name","name","name","name","name","name","name","name","name","neg","neq","new","new","new","new","not","or","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","perform_template_applications","pointer","pow","print","println","proc","push_label","refer","rem","ret","ret","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","return_type","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","set_common_name","simplify","simplify_checked","simplify_checked","simplify_checked","simplify_until_atomic","simplify_until_concrete","simplify_until_const_param","simplify_until_has_members","simplify_until_has_variants","simplify_until_matches","simplify_until_poly","simplify_until_simple","simplify_until_type_checks","simplify_until_union","size_of","strip_template","struct_","structure","sub","substitute","substitute","substitute","substitute","substitute","substitute","substitute","substitute","substitute","substitute_types","substitute_types","sym","template","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","transform_method_call","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","tup","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_check","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unop","var","var","variant_index","while_loop","wildcard","with","with","with","with","module","names","expected","expected","expr","expr","expr","expr","found","found","found","patterns","SourceCodeLocation","borrow","borrow_mut","clone","clone_into","cmp","column","deref","deref_mut","deserialize","drop","eq","filename","fmt","from","get_code","hash","init","into","length","line","offset","parse_asm","parse_frontend","parse_frontend_minimal","parse_lir","parse_vm","partial_cmp","serialize","to_owned","try_from","try_into","type_id","ffi","io","FFIBinding","borrow","borrow_mut","clone","clone_into","cmp","deref","deref_mut","deserialize","drop","eq","fmt","fmt","from","hash","init","input_cells","into","name","new","output_cells","partial_cmp","serialize","to_owned","to_string","try_from","try_into","type_id","Accelerometer","Altimeter","AnalogPin","AnalogPin","Axis","Barometer","Bell","Black","Blower","Blue","BlueLight","Brightness","Brightness","Button","Buzzer","Channel","ClearDisplay","Clock","Color","Compass","ConductivitySensor","Cooler","Custom","Custom","Cyan","DPad","DepthSensor","DigitalPin","DigitalPin","Direction","Down","Fan","FlowSensor","Green","GreenLight","Gyroscope","Heater","Humidity","Input","InputMode","JoyStick","Keyboard","Left","Magenta","Magnetometer","Microphone","MotorSpeed","MoveCursorDown","MoveCursorLeft","MoveCursorRight","MoveCursorUp","Note","Odometer","Orange","Output","OutputMode","PHSensor","Position","Pressure","PressureGauge","PrinterChar","PrinterFloat","PrinterInt","Proximity","Pump","RGB","RainGauge","Random","Red","RedLight","Right","Servo","SetCursorChar","SetCursorColumn","SetCursorPixel","SetCursorRow","Solenoid","SpeakerFrequency","SpeakerVolume","Speedometer","StderrChar","StderrFloat","StderrInt","StdinChar","StdinFloat","StdinInt","StdoutChar","StdoutFloat","StdoutInt","StepperMotor","Temperature","Thermometer","UVSensor","Up","UpdateDisplay","Valve","VolumeSensor","WeightSensor","White","WindDirection","WindSpeed","X","Y","Yellow","Z","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","channel","channel","clock","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","deserialize","drop","drop","drop","drop","drop","drop","drop","drop","eq","eq","eq","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","hash","hash","hash","hash","hash","hash","hash","hash","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","mode","mode","new","new","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","random","serialize","serialize","serialize","serialize","serialize","serialize","serialize","serialize","stderr_char","stderr_float","stderr_int","stdin_char","stdin_float","stdin_int","stdout_char","stdout_float","stdout_int","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","to_string","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","Architecture","CompiledTarget","build_core","build_op","build_std","build_std_op","c","declare_proc","end","get","indentation","name","op","peek","poke","post_funs","postlude","postop","pre_funs","prelude","put","std_op","supports_floats","supports_input","supports_output","version","C","borrow","borrow_mut","declare_proc","default","deref","deref_mut","drop","end","from","get","init","into","name","op","peek","poke","post_funs","postlude","postop","prelude","put","std_op","supports_floats","supports_input","supports_output","try_from","try_into","type_id","version","ACos","ASin","ATan","Add","Add","Alloc","And","ArithmeticRightShift","BitwiseAnd","BitwiseNand","BitwiseNot","BitwiseOr","BitwiseXor","Call","Call","Comment","CoreInterpreter","CoreOp","CoreOp","CoreProgram","Cos","Dec","Deref","Device","Div","Div","Else","End","Error","ExpectedCore","Free","Function","Get","If","Inc","Index","IsNonNegative","IsNonNegative","LeftShift","Load","LogicalRightShift","Move","Mul","Mul","Neg","Neg","Not","Offset","Or","Peek","Poke","Pow","Put","Refer","Rem","Rem","Return","Set","Set","Sin","StandardDevice","StandardInterpreter","StandardOp","StandardProgram","Store","Sub","Sub","Swap","Tan","TestingDevice","ToFloat","ToInt","UnsupportedInstruction","VirtualMachineProgram","Where","While","add_binding","as_float","as_int","begin_else","begin_function","begin_if","begin_while","bitwise_nand","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","call","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","code","code","code","comment","default","default","default","default","default","default","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","drop","drop","drop","drop","drop","drop","drop","drop","drop","end","eq","eq","eq","eq","eq","ffi","ffi_call","ffi_call","ffi_call","ffi_call","ffi_channel","flatten","flatten","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","get","get","get","get","get_functions","get_functions","get_main","get_main","get_main_and_functions","get_main_and_functions","hash","hash","index","init","init","init","init","init","init","init","init","init","input","into","into","into","into","into","into","into","into","into","is_non_negative","load_vector","move_pointer","new","new","new","new_raw","op","op","op","output","output_str","output_vals","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","peek","peek","peek","peek","poke","poke","poke","poke","put","put","put","put","refer","restore","ret","run","run","save","set_float_register","set_float_vector","set_register","set_vector","std_op","std_op","std_op","store_vector","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","where_is_pointer"],"q":[[0,"sage"],[10,"sage::asm"],[65,"sage::asm::core"],[207,"sage::asm::core::CoreOp"],[348,"sage::asm::globals"],[376,"sage::asm::location"],[416,"sage::asm::std"],[510,"sage::asm::std::StandardOp"],[565,"sage::frontend"],[566,"sage::lir"],[1912,"sage::lir::Declaration"],[1914,"sage::lir::Error"],[1924,"sage::parse"],[1957,"sage::side_effects"],[1959,"sage::side_effects::ffi"],[1987,"sage::side_effects::io"],[2293,"sage::targets"],[2319,"sage::targets::c"],[2349,"sage::vm"],[2653,"alloc::string"],[2654,"core::fmt"],[2655,"core::fmt"],[2656,"core::option"],[2657,"core::cmp"],[2658,"core::any"],[2659,"serde::de"],[2660,"core::hash"],[2661,"alloc::vec"],[2662,"alloc::string"],[2663,"core::convert"],[2664,"alloc::boxed"],[2665,"alloc::collections::btree::map"],[2666,"std::collections::hash::map"],[2667,"std::collections::hash::set"],[2668,"core::ops::function"]],"d":["The UNICODE character art for the logo of the language.","The UNICODE character art for the logo of the language, …","The value of the NULL pointer constant.","Assembly Module","","LIR (Low Intermediate Representation) Module","Parsing Module","Side Effects Module","Targets Module","Virtual Machine Module","","A frontend to both the CoreProgram and StandardProgram …","","","","","","","An error generated by assembling some assembly language …","","","","","","","","","","The given global was not defined.","The given label was not defined.","The given instruction was not expected, or cannot be used …","The given instruction did not have a matching “end”. …","Is this standard assembly operation supported by the …","An error generated by the virtual machine.","","","","","Insert a comment into the program.","Core Assembly Variant","Get the current instruction number.","","","","","","","","Returns the argument unchanged.","Get the operation at the given instruction number.","Assembly Global Variables","","Calls U::from(self).","Is the given label defined yet in the operations? I.E., …","Assembly Memory Location","Log all the instructions after the given instruction …","Insert a core operation into the program.","","Standard Assembly Variant","Attempt to insert a standard operation into the program. …","","","","","","Add an integer value from a source location to a …","Logical “and” a destination with a source value.","Arithmetic right shift a destination by a source value. …","Store a list of values at a source location. Then, store …","","","","","","","Get a value in memory and call it as a label ID.","Call a function with a given label.","","Store the comparison of “a” and “b” in a …","Write a set of values to a memory location.","Copy a number of cells from a source referenced location …","A core instruction of the assembly language. These are …","An assembly program composed of core instructions, which …","Decrement the integer value of a location.","Divide a destination location by a source value.","Divide a destination location by a source value. Store the …","Add an “else” clause to an “if the value is not zero…","Terminate a function declaration, a while loop, an if …","Declare a new label.","Get a value from the input device / interface and store it …","Get the address of a location, and store it in a …","Declare a global variable.","Begin an “if the value is not zero” statement over a …","Increment the integer value of a location.","Get the address of a location indexed by an offset stored …","Perform dst = a == b.","Perform dst = a > b.","Perform dst = a >= b.","Perform dst = a < b.","Perform dst = a <= b.","Perform dst = a != b.","Left shift a destination by a source value.","Logical right shift a destination by a source value. This …","Many instructions to execute; conveniently grouped …","Copy a value from a source location to a destination …","Multiply a destination location by a source value.","Negate an integer.","Make this pointer point to the next cell (or the nth next …","Replace a value in memory with its boolean complement.","Logical “or” a destination with a source value.","Pop a number of cells from the stack and store it in a …","Pop a number of cells from a specified stack and store it …","Make this pointer point to the previous cell (or the nth …","Push a number of cells starting at a memory location on …","Get the address of a location and push it to the stack.","Push a const to the stack.","Push a number of cells starting at a memory location onto …","Put a value from a source register to the output device / …","Store the remainder of the destination modulus the source …","Return from the current function.","Set the value of a register, or any location in memory, to …","Set the value of a register, or any location in memory, to …","Subtract a source integer value from a destination …","Swap the values of two locations.","Perform a SIMD addition over a vector of integers. This …","Perform a vector “And” operation. This will perform a …","Perform a SIMD arithmetic right shift operation over a …","","","","","","","Decrement a vector of integers.","Perform a SIMD division over a vector of integers. This …","Perform a SIMD “is >= zero” operation over a vector of …","Increment a vector of integers.","Perform a SIMD pointer index operation over a vector of …","Perform a SIMD left shift operation over a vector of …","Perform a SIMD logical right shift operation over a vector …","Perform a SIMD multiplication over a vector of integers. …","Negate a vector of integers using SIMD.","Perform a vector “Not” operation. This will replace …","Perform a SIMD pointer arithmetic operation over a vector …","Perform a vector “Or” operation. This will perform a …","Perform a SIMD remainder over a vector of integers. This …","Set the vector values of a destination.","Perform a SIMD subtraction over a vector of integers. This …","Begin a “while the value is not zero” loop over a …","Assemble a program of core assembly instructions into the …","","","","","","","","","","","The list of core assembly instructions in the program.","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","Calls U::from(self).","Calls U::from(self).","","Create a new program of core assembly instructions.","","","","Push a string literal as UTF-8 to the stack.","Put a string literal as UTF-8 to the output device.","","","Allocate a string on the stack, and store its address in a …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","A lookup for all the global variables in an assembly …","Add a global variable to the list of globals.","","","","","Create a new empty Globals lookup.","","","","","","","Returns the argument unchanged.","Get the location, and size of a global variable.","Get the location of a global variable.","Get the size of a global variable. This is the number of …","Get the size of the global variables. This is the number …","","Calls U::from(self).","Create a new empty Globals lookup.","Resolve the global variables in a location to produce an …","","","","","","","The “A” general purpose register.","A fixed position in the tape (a constant address known at …","The “B” general purpose register.","The “C” general purpose register.","The “D” general purpose register.","The “E” general purpose register.","The “F” general purpose register.","The frame pointer register.","The Global Pointer register. This is used to access global …","A global variable.","Use the value of a cell on the tape as an address. For …","A location in memory (on the tape of the virtual machine).","Go to a position in memory, and then move the pointer …","","The stack pointer register.","","","","","","","Get the location of the value pointed to by this location.","","","","","","","Returns the argument unchanged.","","","Calls U::from(self).","Get the location offset by a constant number of cells from …","","","","","","","","Perform inverse Cos on a cell (float) and store the result …","Perform inverse Sin on a cell (float) and store the result …","Perform inverse Tan on a cell (float) and store the result …","Add the source cell (float) to the destination cell …","Take the value in the operand cell. Allocate that number …","Call a foreign function.","Write some constant values to a location on the tape","Execute a core instruction.","Perform Cos on a cell (float) and store the result in the …","Divide the destination cell (float) by the source cell …","Free the memory allocated at the address stored in the …","Perform dst = a > b.","Perform dst = a < b.","Multiply the source cell (float) by the destination cell …","Negate the value of a cell (float) and store the result in …","Raise a cell (float) to the power of another cell (float).","Push some constant values to the stack.","Perform the modulo operation on the destination cell …","Set the value of a cell to a constant float.","Perform Sin on a cell (float) and store the result in the …","Take the square root of a cell (float).","A standard instruction of the assembly language. These are …","A program composed of standard instructions, which can be …","Subtract the source cell (float) from the destination cell …","Perform Tan on a cell (float) and store the result in the …","Take the integer value stored in a cell and store the …","Take the float value stored in a cell and store the …","Perform a SIMD floating point inverse cosine operation.","Perform a SIMD floating point inverse sine operation.","Perform a SIMD floating point inverse tangent operation.","Perform a SIMD floating point addition operation.","Perform a SIMD floating point cosine operation.","Perform a SIMD floating point division operation.","Perform a SIMD floating point greater than or equal to …","Perform a SIMD floating point multiplication operation.","Perform a SIMD floating point negation operation.","Perform a SIMD floating point power operation.","Perform a SIMD floating point remainder operation.","Set the vector values of a destination.","Perform a SIMD floating point sine operation.","Perform a SIMD floating point subtraction operation.","Perform a SIMD floating point tangent operation.","Assemble the program into a virtual machine program.","","","","","","","","","The list of standard assembly instructions in the program.","Get the current instruction number.","","","","","","","","","","","","","","","","Returns the argument unchanged.","","Returns the argument unchanged.","Get the operation at the given instruction number.","","","Calls U::from(self).","Calls U::from(self).","Is the given label defined yet in the operations?","Create a new program of core assembly instructions.","Add a core operation to the program.","","","","","Add a standard operation to the program.","","","","","","","","","","","The first cell in the comparison (left hand side).","The first cell in the comparison (left hand side).","The second cell in the comparison (right hand side).","The second cell in the comparison (right hand side).","The beginning of the constant data.","The destination cell.","The destination cell.","The destination cell.","The destination cell.","The destination cell.","The destination cell.","The destination cell.","The destination cell.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","The source cell.","The source cell.","The source cell.","The source cell.","The source cell.","The source cell.","","","","","","","","The constant data.","","","","","A boolean “And” operation between two values.","An error with some annotation about the source code that …","","An expression along with data about its source code …","An annotation for metadata about an LIR expression. This …","The expression equal to any other expression.","Unchecked access to a value. This is used to override …","A type reserved by the compiler. This type is equal to any …","Apply a function with some arguments.","A type that constructs a concrete type from a polymorphic …","Tried to apply a non-procedure to some arguments.","Tried to apply a non-template type to some arguments.","An arithmetic operation.","An array of constant values.","An array of expressions.","An array of a given type, with a constant size.","Cast a constant expression to another type.","Cast an expression to another type.","An error caused by trying to assemble invalid code …","An assignment operation. This is used to implement …","A trait used to implemented an assignment operation.","Perform an assignment operation on two expressions.","A trait used to implement a binary operation.","Perform a binary operation on two expressions.","A boolean “BitwiseAnd” operation between two values.","A boolean “BitwiseNand” operation between two values.","A boolean “BitwiseNor” operation between two values.","","A boolean “BitwiseOr” operation between two values.","A boolean “BitwiseXor” operation between two values.","A constant boolean value.","The type of a boolean value.","An annotation for compiler-generated code.","An annotation for a constant.","A constant integer value representing a cell on the tape.","The type of the most basic unit of memory.","A constant chararacter.","The type of a character.","A comparison operation between two values.","A trait which allows an LIR expression to be compiled to …","Tried to compile a polymorphic procedure without …","Is this expression compiler-generated?","A constant expression.","A compiletime expression.","A constant expression.","","A constant literal used in a type expression, like a …","Is this expression a constant?","A builtin pseudo-procedure implemented in the core …","A builtin implemented in handwritten core assembly.","Recursion depth exceeded when trying to confirm a type’s …","An annotation for dead code.","Get the Union data associated with a tagged union …","Is this expression dead code?","","A declaration of a variable, function, type, etc.","Bind a list of types in a constant expression.","Declare any number of variables, procedures, types, or …","","Dereference this expression (i.e. get the value it points …","Store an expression to an address (a pointer).","Tried to dereference a non-pointer.","","","Duplicate implementations of a member for a type","An enumeration of a list of possible named values. A …","A tagged union of constant values.","A tagged union: a typechecked union of different variants. …","An enumeration of a list of possible types. This is a sum …","An environment under which expressions and types are …","","An LIR compilation error.","TODO: Add variants for LetProc, LetVar, etc. to support …","A foreign function declaration.","A typed procedure which calls a foreign function. This is …","A foreign function interface binding.","A constant floating point value.","The floating-point number type.","Import an element from a module.","","","Get the size of something in memory (number of cells).","Get the type associated with a value under a given …","","","An if-then-else expression.","An if-let expression.","Immutable access to a value. This is the default way to …","Declare associated constants and procedures for a type.","Index an array or pointer with an expression that …","A constant integer value.","The integer type.","Invalid type casting expression.","Invalid assignment operation (assign, add_assign, …","Invalid assign op types (incorrect types).","Invalid binary operation (add, subtract, and, or) …","Invalid binary op types (incorrect types).","Invalid constant expression.","Invalid Index expression (incorrect types).","Tried to match over an expression that cannot be matched …","Cannot monomorphize a constant expression.","Tried to use a pattern that is not valid for the given …","Tried to use a pattern that is not valid for the given …","Invalid Refer expression. The compiler was not able to …","Invalid number of template arguments to a type.","Invalid ternary operation (if) expression (incorrect …","Invalid ternary op types (incorrect types).","Invalid unary operation (negate, not) expression …","Invalid unary op types (incorrect types).","An annotation for live code.","","","Bind a type to a name in a temporary scope.","The source code location of the expression.","Many annotations can be attached to an expression. This is …","Many declarations.","A block of expressions. The last expression in the block …","A match expression.","Get an attribute of a constant expression.","Get a field or member from a structure, union, or tuple. …","Tried to access an undefined member of a tuple, struct, or …","Mismatched mutability","Mismatched types","Declare a module","Monomorphize a constant expression with some type …","","Mutability of a pointer. This is used to provide type …","Mutable access to a value.","A constant expression that evaluates to None. This …","","Tried to create an array with a negative length.","The type of an expression that will never return, or doesn…","","Invalid pattern for a match expression.","Got another type when expecting an integer, bool, or char.","Expected a symbol, but got something else.","No annotation.","The unit, or “void” instance.","The type of void expressions.","A boolean “Not” operation on a value.","","The null pointer constant.","A constant enum variant.","A boolean “Or” operation between two values.","A pattern which can be matched against an expression.","","A pointer to another type.","A polymorphic, parametric type. This type is used with the …","A polymorphic procedure.","A polymorphic procedure declaration.","A polymorphic procedure of LIR code which can be applied …","","A procedure.","A procedure declaration.","A procedure with a list of parameters and a return type.","A monomorphic procedure of LIR code which can be applied …","Print a value to a given output.","Recursion depth exceeded when trying to evaluate a …","Recursion depth exceeded when trying to confirm a type’s …","Reference this expression (i.e. get a pointer to it).","","Return a value from a function.","This is the maximum number of times a type will be …","Simplify an expression while maintaining structural …","Get the size of an expression’s type (in cells) as a …","Tried to get the size of a template type.","Get the size of a type (in cells) as a constant int.","A builtin pseudo-procedure implemented in the standard …","A builtin implemented in handwritten standard assembly.","A static variable declaration.","A structure of constant values.","A structure of fields to expressions.","","A tuple with named members. This is a product type.","","A named constant.","","A named type.","A symbol was used, but not defined.","An annotation for a temporary.","Get the Enum value of the tag associated with a tagged …","","Is this expression a temporary?","A trait used to implement a ternary operation.","Perform a ternary operation on three expressions.","A tuple of constant values.","A tuple of expressions.","","A heterogenous collection of types. This is a product type.","The representation of a type in the LIR type system.","A type as a constant expression.","A type declaration.","A trait object. This is internally represented as an …","A trait used to enforce type checking.","A type was used, but not defined.","Get the type of an expression. (as an array of chars)","Tried to define a type that already exists.","An annotation for user-generated code.","A trait used to implement a unary operation.","Perform a unary operation on two expressions.","An error caused by unexpectedly passing a constant …","","A union of constant values.","A union: a collection of named fields. The Type value is …","A union of a list of possible types mapped to named …","This type is identified by its name. Most types are …","Tried to instantiate a type that cannot be sized. This is …","Expression uses an operation unsupported by the target.","Unused expression returned a non-None value.","A variable declaration.","A variable declaration with a pattern.","","The variant of an enum is not defined.","A constant, compile time if-then-else expression.","Create a while loop: while the first expression evaluates …","","","Add this expression to another.","","","Add monomorphized methods for a given monomorph of a …","Construct a new pattern which binds to several alternate …","Logical and this expression with another.","Annotate an error with some metadata.","Annotate this constant expression with a source code …","An annotated expression with some metadata.","Apply this procedure or builtin to a list of expressions …","Apply this expression as a procedure to some arguments.","Apply this template type with some type arguments.","This associated function returns whether or not a set of …","The arguments of the builtin. These will be typechecked …","The arguments of the builtin. These will be typechecked …","Try to get this constant expression as a boolean value.","Try to get this constant expression as a character.","Try to get this constant expression as a float.","Try to get this constant expression as an integer.","Try to get this constant expression as a symbol (like in …","Cast an expression as another type.","Cast an expression as another type.","Perform an AssignOp on this expression.","Perform an AssignOp on this expression.","BitwiseAnd this expression with another.","BitwiseOr this expression with another.","BitwiseAnd this expression with another.","BitwiseAnd this expression with another.","","BitwiseOr this expression with another.","","Bitwise this expression with another.","The list of assembly instructions to be pasted into the …","The list of assembly instructions to be pasted into the …","Construct a new pattern which matches a constant boolean.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Checks if the operation can be applied to the given types.","Checks if the operation can be applied to the given type.","Checks if the operation can be applied to the given types.","Checks if the operation can be applied to the given types.","","","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this unary operation be applied to the given type?","Can this unary operation be applied to the given type?","Can this binary operation be applied to the given types?","Can this binary operation be applied to the given types?","Can this unary operation be applied to the given type?","Can this unary operation be applied to the given type?","Can this unary operation be applied to the given type?","Can this unary operation be applied to the given type?","Can this unary operation be applied to the given type?","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Checks if the operation can be applied to the given …","Can this type be cast to another type?","Can a pointer of this mutability decay to a pointer of …","Can this type decay into another type?","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Clones the operation into a boxed trait object.","Clones the operation into a boxed trait object.","Clones the operation into a boxed trait object.","Clones the operation into a boxed trait object.","","","","Clone this operation into a trait object.","Clone this binary operation into a box.","Clone this binary operation into a box.","Clone this binary operation into a box.","","Clone this binary operation into a box.","Clone this binary operation into a box.","","Clone this operation into a box.","Clone this operation into a box.","Clone this binary operation into a box.","Clone this operation into a box.","Clone this operation into a box.","Clone this operation into a box.","Clone this operation into a box.","Clone this operation into a box.","Clone this operation into a box.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Compile the expression into an assembly program.","Compile the expression into an assembly program.","Compiles the operation on the given expressions.","Compiles the operation on the given expressions.","Compiles the operation on the given expression.","Compiles the operation on the given expression.","Compiles the operation on the given expressions.","Compiles the operation on the given expressions.","Compiles the operation on the given expressions.","Compiles the operation on the given expressions.","Compiles the operation on the given expressions.","Compiles the operation on the given expressions.","Compile the assignment operation.","","","","","","","","Compiles the operation on the given types. (Generates the …","Compiles the operation on the given type. (Generates the …","Compiles the operation on the given types. (Generates the …","Compiles the operation on the given types. (Generates the …","","","Compile the binary operation.","Compile the assignment operation.","Compile the binary operation.","Compile the binary operation.","Compile the binary operation.","","Compile the binary operation.","Compile the binary operation.","Compile the binary operation.","Compile the unary operation.","Compile the unary operation.","Compile the binary operation.","Compile the binary operation.","Compile the unary operation.","Compile the unary operation.","Compile the unary operation.","Compile the unary operation.","Compile the unary operation.","Does this type contain a symbol with the given name? This …","","Let-bind the pattern to the given expression. This will …","","","Define multiple types with the given names under this …","Define a variable in the current scope. This will …","","","","","","","Dereference this expression (i.e. get the value it points …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Dereference this expression (i.e. get the value it points …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","Formats the operation for display.","","Divide this expression by another.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Is this expression greater than another?","","","","","","","","","","","","","","","","","","","","","","","","","","Are two types structurally equal?","Evaluates the operation on the given constant expressions.","Evaluates the operation on the given constant expression.","Evaluates the operation on the given constant expressions.","Evaluates the operation on the given constant expressions.","Evaluate this constant expression at compile time, and get …","","","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this unary operation on the given constant values.","Evaluate this unary operation on the given constant values.","Evaluate this binary operation on the given constant …","Evaluate this binary operation on the given constant …","Evaluate this unary operation on the given constant values.","Evaluate this unary operation on the given constant values.","Evaluate this unary operation on the given constant values.","Evaluate this unary operation on the given constant values.","Evaluate this unary operation on the given constant values.","Get a field from a structure, union, or tuple.","Get a field from a structure, union, or tuple.","Construct a new pattern which matches a constant float.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","","","","Returns the argument unchanged.","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","","Is this expression greater than or equal to another?","","Get the arguments of the procedure.","","Get the map of new variables and their types which are …","Get the body of the procedure.","Get the type of a branch with a given expression matched …","Get the name of the procedure known to the LIR front-end.","Get the mangled name of the procedure. The procedure’s …","","Get the template arguments for the monomorph (this type) …","Get the name of this polymorphic procedure. This is not …","Get the return type of the procedure.","Get the first argument’s mutability (if it is a pointer)","Get the size of something in memory (number of cells).","Get the size of something in memory (number of cells).","Get the size of something in memory, but limit the number …","","","","","","","","","Get the template parameters for this template type.","Get the type associated with a value under a given …","Get the type associated with a value under a given …","Get the type of a value under a given environment and check","","","","","","","","Get the type of an associated constant of a type.","","Is this expression greater than another?","","","Does this type have an element type matching the supplied …","Does this annotation have a location?","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Index an array or pointer with an expression that …","Generate an if letexpression, which matches a given expr, …","Create an if-then-else statement with this expression as …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Construct a new pattern which matches a constant integer.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Is this type an irreducible, atomic type?","Is this compiler-generated?","Is this type simplified enough to get information about …","Is this type a constant parameter?","Is this data protected against mutation?","Is this dead code?","Is this pattern exhaustive?","Is this annotation a location?","","Is this type a monomorph of a given template type?","Can this data be accessed mutably?","Is this annotation none?","Is this a polymorphic function?","","Is this type recursive?","Is first argument of function a reference?","Is this type in a simple form? A simple form is a form …","Is this a temporary?","Is this expression less than or equal to another?","Create a let-bound type.","Create a let binding for a constant expression.","Create several const bindings at onces.","Create a proc binding for a procedure.","Create several proc bindings at onces.","Create a let binding for an type.","Create several type bindings at onces.","Create a let binding for an expression.","Create a let binding for an expression, and define …","Get the location of this annotation.","Is this expression less than another?","Create a collection of declarations","Generate an expression which evaluates a match expression, …","Create a module with a given name and a list of …","","Take some type arguments and produce a monomorphized …","Multiply this expression by another.","","","","","","","","","The name of the builtin. This isn’t used in compilation, …","The name of the builtin. This isn’t used in compilation, …","Get the remainder of this expression divided by another.","Is this expression greater than or equal to another?","Create a new assignment operation.","Create a new FFI procedure.","Construct a new procedure with a given list of arguments …","Construct a new polymorphic procedure with type …","Logical not this expression.","Logical or this expression with another.","","","","","","","","","","","","","","","","","","","","","","","Perform type applications if possible.","Construct a new pattern which matches a pointer.","Get the power of this expression to another.","","","Construct a procedure.","Push this procedure’s label to the stack.","Reference this expression (i.e. get a pointer to it).","Get the remainder of this expression divided by another.","The return value the builtin will leave on the stack after …","The return value the builtin will leave on the stack after …","Gets the type of the operation on the given expressions.","Gets the type of the operation on the given expressions.","Gets the type of the operation on the given expression.","Gets the type of the operation on the given expression.","Gets the type of the operation on the given expressions.","Gets the type of the operation on the given expressions.","Gets the type of the operation on the given expressions.","Gets the type of the operation on the given expressions.","","","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this unary …","Get the type of the result of applying this unary …","Get the type of the result of applying this binary …","Get the type of the result of applying this binary …","Get the type of the result of applying this unary …","Get the type of the result of applying this unary …","Get the type of the result of applying this unary …","Get the type of the result of applying this unary …","Get the type of the result of applying this unary …","","","","","","","","","","","","","This is just for debugging purposes. This sets the common …","Simplify an expression while maintaining structural …","Simplify an expression while maintaining structural …","","","","Simplify until the type is concrete.","Simplify until the type is concrete.","Simplify a type until you can get its members.","Simplify a type until you can get its variants.","Simplify an expression until it matches a given function …","Simplify until the type is a polymorphic type.","","Simplify until the type passes the type checker.","Simplify a type until it’s a union.","Get the size of an expression.","Strip the template arguments to get the inner type","Construct a new pattern which matches a struct with a …","Create a structure of fields to expressions.","Subtract an expression from this expression.","Substitute a type for a given name in the environment.","","Substitute a type in a given expression.","","","","","","Substitute all occurences of a symbol with another type. …","","","Construct a new pattern which matches a symbol with a …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Construct a new pattern which matches a tuple of patterns.","Type check the expression.","Typechecks the operation on the given expressions.","Typechecks the operation on the given expressions.","Typechecks the operation on the given expression.","Typechecks the operation on the given expression.","Typechecks the operation on the given expressions.","Typechecks the operation on the given expressions.","Typechecks the operation on the given expressions.","Typechecks the operation on the given expressions.","","","","Type-check a pattern match of an expression against this …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Apply a unary operation to this expression.","Evaluate a variable in the current scope.","Evaluate a variable in the current scope.","Calculate the integral value of a variant in an enum.","Create a while statement with this expression as the …","Construct a new pattern which matches any expression.","Return this expression, but with a given declaration in …","Return this expression, but with a given declaration in …","","","","","","","","","","","","","","","A struct representing a location in the source code. This …","","","","","","","","","","","","","","Returns the argument unchanged.","","","","Calls U::from(self).","","","","Parse Core and Standard variants of assembly source code. …","Parse frontend sage code into an LIR expression.","","Parse LIR code as an LIR expression.","Parse Core and Standard variants of virtual machine source …","","","","","","","Foreign Function Interface","I/O Module","This is an FFI binding, which is used to call a foreign …","","","","","","","","","","","","","Returns the argument unchanged.","","","","Calls U::from(self).","","Create a new FFI binding.","","","","","","","","","Input from an accelerometer (in meters per second per …","Input from altitude sensor (in meters)","Electrical device input modes (These should typically be …","Electrical device output modes Set the voltage of a given …","The different axes an input or output might use.","Input from a barometer (pressure in atmospheres)","Ring a bell (in hertz)","Black","Set the pressure of a given blower (in atmospheres)","Blue","Blue light intensity (in lux)","Input from a light sensor (in lux)","Lighting device output modes Set the brightness of a given …","Input from a button (0=not pressed, 1=pressed)","Sound output modes Ring a given buzzer (in hertz)","The channel to use for a given I/O mode.","Clear the display","Physical sensor input modes (These should typically be …","The different output colors a program might use.","Input from a compass (degrees)","Input from a conductivity sensor (in siemens per meter)","Turn a cooler on or off (0=off, 1=on)","Custom output modes A custom input mode (for use with a …","Custom output modes A custom output mode (for use with a …","Cyan","User input modes (These should typically be used for games …","Input from depth sensor (in meters)","Input from a digital input (0=low, 1=high)","Set the state of a given digital output (0=low, 1=high)","The different directions a D-Pad a might use.","","Set the pressure of a given fan (in atmospheres)","Input from a flow sensor (in liters per second)","Green","Green light intensity (in lux)","Input from a gyroscope (in degrees per second) around a …","Turn a heater on or off (0=off, 1=on)","Input from a humidity sensor (in percent)","An input source for a program.","The different types of input modes a program might use.","Input from a JoyStick the degree of displacement in a …","Input from keyboard (ASCII character)","","Magenta","Input from a magnetometer (in teslas) in a given axis","Input from a microphone (frequency in hertz)","Set the speed of a given motor (in revolutions per minute)","Move the cursor down on the display","Move the cursor left on the display","Move the cursor right on the display","Move the cursor up on the display","Play a given note (in hertz)","Input from an odometer (in meters)","Orange","An output destination for a program.","The different types of output modes a program might use.","Input from a pH sensor (in pH)","Input from a position sensor in a given axis (x, y, z)","Set the pressure of a given vacuum/pressurizer …","Engineering / Science sensor input modes Input from a …","Alternative output modes for standard output Printer …","Printer (float)","Printer (integer)","Input from a distance sensor (in meters)","Set the pressure of a given pump (in atmospheres)","RGB ","Input from a rain gauge (in millimeters)","Special input modes A random number","Red","Environment sensor input modes (These should typically be …","","Set the position of a given servo (in radians)","Write a character to the display","Set the cursor column on the display","Set the color of a given pixel on the display","Set the cursor row on the display","Set the polarity of a solenoid (0=off, 1=on)","Set the frequency of a given speaker (in hertz)","Set the volume of a given speaker (in percent)","Navigation input modes (These should typically be …","Standard error (ASCII character)","Standard error (float)","Standard error (integer)","Standard input modes (The standard interface is typically …","Standard input (float)","Standard input (integer)","Standard output modes Standard output (ASCII character)","Standard output (float)","Standard output (integer)","Robotics device output modes Set the position of a given …","Set the temperature of a given heating/cooling device …","Input from a thermometer (degrees K)","Input from a UV sensor (in watts per square meter)","","Display output modes Update the display","Set the position of a given valve (0=closed, 1=open)","Input from a volume sensor (in liters)","Input from a weight sensor (in kilograms)","White","Input from a wind direction sensor (in degrees)","Input from a wind speed sensor (in meters per second)","","","Yellow","","","","","","","","","","","","","","","","","","The channel to use for the input.","The channel to use for the output.","The time (in seconds) since the program started","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","","","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","The mode of the input.","The mode of the output.","Create a new input source.","Create a new output destination.","","","","","","","","","A random number","","","","","","","","","Output to STDERR (ASCII character)","Output to STDERR (float)","Output to STDERR (integer)","Input from STDIN (ASCII character)","Input from STDIN (float)","Input from STDIN (integer)","Output to STDOUT (ASCII character)","Output to STDOUT (float)","Output to STDOUT (integer)","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","A trait for a target architecture to be compiled to.","Implement a compiler for the given target.","Compile the core variant of the machine code (must be …","","Compile the standard variant of the machine code (should …","","C Target","Compile the declaration of a procedure.","Compile an End instruction (with the matching If or While …","Get a value from the given input stream (mode + channel).","The string used for indentation.","The name of the target architecture.","Compile a CoreOp instruction.","Peek a value from the device connected to the program.","Poke a value to the device connected to the program.","The code after the function definitions.","The code after the program ends.","The code after each instruction.","The code before the function definitions.","The code before the program starts.","Put a value to the given output stream (mode + channel).","Compile a StandardOp instruction.","Whether or not the target architecture supports floating …","Whether or not the target architecture supports the given …","Whether or not the target architecture supports the given …","The version of the target architecture.","The type for the C target which implements the Target …","","","","","","","","","Returns the argument unchanged.","","","Calls U::from(self).","","","","","","","","","","","","","","","","","","Store the inverse-cosine of the register (as a float) into …","Store the inverse-sine of the register (as a float) into …","Store the inverse-tangent of the register (as a float) …","Add the value pointed to on the tape to the register. The …","Add the value pointed to on the tape to the register (as …","Take the value of the register, and allocate that number …","Boolean-and the register and the value pointed to on the …","Interpret the register’s value as a signed integer. …","Perform bitwise and on the cell and the value pointed to …","Perform bitwise nand on the cell and the value pointed to …","Bitwise not the register. Store the result in the register.","Perform bitwise or on the cell and the value pointed to on …","Perform a bitwise xor on the cell and the value pointed to …","Calls the nth function defined in the program, where n is …","Call a foreign function interface function.","A comment in the machine code (not in the compiled output).","The interpreter which runs the virtual machine program.","An individual core virtual machine instruction.","Execute a core instruction.","A program of only core virtual machine instructions.","Store the cosine of the register (as a float) into the …","Decrement the register.","The pointer is made equal to the value pointed to on the …","Create an input / output device for the virtual machine …","Divide the register by the value pointed to on the tape. …","Divide the register by the value pointed to on the tape …","Begin an “else” conditional.","End a conditional.","An error generated by the virtual machine.","When the virtual machine attempts to get the program as …","Free the memory pointed to by the register.","Create a new function.","Get a value from an input source and store it in the …","Begin an “if the register is not zero” conditional.","Increment the register. The argument is the size of the …","Interpret the register’s value as a pointer to a cell. …","Make the register equal to 1 if the register is …","Make the register equal to the integer 1 if the register …","Left shift the cell by the value pointed to on the tape. …","Store the value pointed to on the tape to the register.","Logical right shift the cell by the value pointed to on …","Move the pointer on the tape by a number of cells.","Multiply the register by the value pointed to on the tape. …","Multiply the register by the value pointed to on the tape …","Negate the register. The argument is the size of the …","Negate the value of the register (as a float).","Boolean-not the register (0 if the register is non-zero, 1 …","Interpret the register’s value as a pointer to a cell. …","Boolean-or the register and the value pointed to on the …","Get a value from the input interface / device and store it …","Write the value of the register to the output interface / …","Store the value of the register (as a float) to the power …","Write the value of the register to an output source.","The last “deref” operation is undone; the pointer is …","Store the remainder of the register and the value pointed …","Store the remainder of the register and the value pointed …","Return from the current function.","Set the register equal to a constant value.","Set the register equal to a constant floating point value.","Store the sine of the register (as a float) into the …","A device used for standard input and output. This simply …","The interpreter which runs the standard variant of virtual …","An individual standard virtual machine instruction.","A program of core and standard virtual machine …","Store the register to the value pointed to on the tape.","Subtract the value pointed to on the tape from the …","Subtract the value pointed to on the tape from the …","Swap the value of the register with the value pointed to …","Store the tangent of the register (as a float) into the …","A device used for testing the compiler. This simply keeps …","Convert the register from an integer to a float.","Convert the register from a float to an integer.","When an instruction is unsupported for a given …","An interface to conveniently create virtual machine …","Store the value of the pointer to the register.","Begin a “while the register is not zero” loop.","","A function to reinterpret the bits of an integer as a …","A function to reinterpret the bits of a float as an …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","FFI call to the device. This will get the FFI binding for …","","","","","Flatten a core program so that all of its functions are …","Flatten a core program so that all of its functions are …","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Get the next input (from a given input source).","","","","Get the code for each function.","Get the code for each function.","Get the code outside of any functions.","Get the code outside of any functions.","Get the code outside of any functions, and the code for …","Get the code outside of any functions, and the code for …","","","","","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","","Create a new testing device with some given sample input.","","","","","","Get the output of the testing device as a string (ascii).","","","","","","","Peek at the next value in the FFI buffer for the FFI …","","","","Poke a value into the FFI buffer for the FFI function …","","","","Put the given value to the given output destination.","","","","","","","Run a core program using this interpreter and its device.","Run a core program using this interpreter and its device.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"i":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,3,0,3,1,1,1,1,1,1,1,1,3,0,1,1,3,0,3,3,1,0,3,1,1,1,1,1,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,0,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,17,17,10,17,10,17,10,17,10,17,10,17,17,17,17,10,17,10,17,10,17,10,17,10,17,17,10,10,17,10,17,17,10,17,10,17,10,17,17,17,17,10,10,10,17,10,10,17,17,10,17,10,17,10,17,10,17,10,105,106,107,108,109,110,111,112,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,105,106,107,108,109,110,111,145,146,147,148,149,150,151,152,153,154,155,156,157,158,115,142,143,158,114,122,123,124,125,126,129,130,131,132,133,137,138,139,140,141,142,143,159,144,152,153,154,155,156,157,159,144,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,130,131,134,135,136,137,138,139,140,143,159,145,147,148,149,150,151,152,153,154,155,156,145,146,0,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,0,25,0,0,0,0,0,0,0,25,25,0,25,0,0,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,28,28,11,28,11,28,11,28,11,28,28,28,28,11,28,11,28,11,28,11,28,11,28,28,11,11,28,28,11,28,28,11,28,11,28,28,28,28,11,28,11,28,28,11,28,11,28,11,28,11,28,11,160,161,160,161,162,163,164,165,166,167,168,160,161,169,170,171,172,173,174,175,176,177,178,179,180,181,182,169,170,171,172,173,174,175,176,177,178,179,180,181,182,163,164,165,166,167,168,169,170,171,172,173,175,182,162,0,0,49,37,0,36,35,30,0,35,67,34,30,34,36,36,0,35,30,34,35,30,36,0,0,30,0,30,0,0,0,0,0,0,35,34,38,38,35,34,35,34,0,0,36,38,31,0,30,37,34,38,0,35,36,38,0,38,59,0,35,30,0,30,30,36,59,49,36,34,35,30,34,0,57,0,0,31,0,35,35,34,31,31,0,0,0,57,57,30,30,67,31,30,35,34,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,38,57,57,34,38,38,31,30,30,35,30,36,36,36,31,35,49,0,67,30,0,36,34,0,36,36,36,38,35,34,0,57,35,35,0,0,37,34,34,35,31,0,49,35,31,34,0,0,36,36,30,49,30,34,0,35,36,35,0,35,31,35,30,37,34,49,35,37,34,36,38,0,35,38,0,30,35,30,37,34,0,35,31,34,0,36,35,36,38,0,30,36,36,35,30,34,34,36,36,36,31,31,37,36,30,30,37,31,30,31,33,34,37,30,36,35,30,35,30,34,37,68,69,35,35,35,35,35,35,30,30,30,30,30,30,30,38,30,38,30,68,69,37,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,43,43,44,44,45,45,46,46,34,67,34,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,43,44,45,46,38,47,48,51,52,53,54,55,56,57,58,59,60,63,64,65,66,67,74,74,43,43,44,44,45,45,46,46,47,49,50,74,35,30,68,69,70,71,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,34,59,37,33,67,33,33,38,33,36,35,31,30,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,38,33,36,35,31,30,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,38,35,31,30,37,68,69,70,71,72,67,34,43,43,44,44,45,45,46,46,59,30,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,43,44,45,46,38,35,31,30,30,47,48,51,52,53,54,55,56,57,58,59,60,63,64,65,66,37,68,69,70,71,72,67,34,35,34,43,44,45,46,35,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,35,30,37,38,33,33,36,36,35,35,31,31,30,30,47,47,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63,64,64,65,65,66,66,37,37,68,68,69,69,70,70,71,71,72,72,67,67,34,34,38,38,33,36,36,35,35,35,35,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,30,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,67,34,72,30,33,71,33,37,71,37,71,71,30,34,72,71,34,79,79,79,35,30,68,69,70,71,72,34,34,80,80,80,35,30,68,69,70,71,72,33,72,30,30,33,34,38,38,35,31,30,47,48,51,52,53,54,55,56,57,58,59,60,63,64,65,66,37,68,69,70,71,72,67,34,30,37,30,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,37,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,34,38,34,34,67,38,37,38,30,34,67,38,34,34,34,34,34,38,30,34,30,30,30,30,30,30,30,30,38,30,31,37,31,35,72,30,43,43,44,44,45,45,46,46,68,69,30,30,50,70,71,72,30,30,43,44,45,46,38,47,48,51,52,53,54,55,56,57,58,59,60,63,64,65,66,67,34,37,30,30,30,35,71,30,30,68,69,43,43,44,44,45,45,46,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,38,35,31,30,37,68,69,70,71,72,67,34,71,81,81,35,34,34,34,34,34,34,34,34,34,34,34,30,34,37,30,30,80,35,30,68,69,70,71,72,34,80,80,37,35,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,30,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,37,84,43,43,44,44,45,45,46,46,35,31,30,37,68,69,70,71,72,34,38,33,36,35,31,30,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,37,68,69,70,71,72,67,34,30,35,30,34,30,37,35,30,71,72,183,183,184,185,186,184,185,187,186,184,185,187,0,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,0,0,0,0,0,75,75,75,75,75,75,0,0,0,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,90,90,90,91,0,90,91,89,91,89,90,90,91,90,91,0,91,90,0,90,90,91,90,91,89,90,90,90,91,0,88,91,90,89,90,90,91,90,0,0,90,90,88,89,90,90,91,91,91,91,91,91,90,89,0,0,90,90,91,90,91,91,91,90,91,89,90,90,89,90,88,91,91,91,91,91,91,91,91,90,91,91,91,90,90,90,91,91,91,91,91,90,90,88,91,91,90,90,89,90,90,87,87,89,87,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,86,23,86,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,87,88,88,89,89,90,90,91,91,92,92,86,86,23,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,86,23,86,23,87,88,89,90,91,92,86,23,86,87,88,89,90,91,92,86,23,23,23,23,86,86,86,23,23,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,87,88,89,90,91,92,86,23,0,0,93,93,93,93,0,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,0,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,95,95,95,94,95,95,94,94,94,94,94,94,94,94,95,94,0,0,95,0,95,94,94,0,94,95,94,94,0,9,95,94,94,94,94,94,94,95,94,94,94,94,94,95,94,95,94,94,94,95,95,95,94,94,94,95,94,94,95,95,0,0,0,0,94,94,95,94,95,0,95,95,9,0,94,94,99,0,0,100,100,100,100,100,101,102,18,94,29,95,103,99,9,101,102,18,94,29,95,103,99,9,100,18,94,29,95,99,9,18,94,29,95,99,9,18,94,100,18,29,100,101,102,18,29,103,99,101,102,100,18,94,29,95,103,99,9,101,102,18,94,29,95,103,99,9,101,102,18,94,29,95,103,99,9,100,18,94,29,95,9,103,104,100,103,99,103,18,29,18,94,94,29,95,95,103,99,9,9,101,102,18,94,29,29,95,103,99,9,104,100,103,99,18,29,18,29,18,29,18,94,100,101,102,18,94,29,95,103,99,9,103,101,102,18,94,29,95,103,99,9,100,100,100,101,102,103,103,100,18,29,103,103,103,18,94,29,95,9,104,100,103,99,104,100,103,99,104,100,103,99,100,100,100,101,102,100,100,100,100,100,100,18,29,100,18,94,29,95,99,9,18,94,29,95,9,101,102,18,94,29,95,103,99,9,101,102,18,94,29,95,103,99,9,101,102,18,94,29,95,103,99,9,100],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[1,1],[[-1,-2],2,[],[]],[[3,4],2],0,[3,5],[5,-1,[]],[5,-1,[]],[5,2],[[1,1],6],[[1,7],8],[[1,7],8],[9,1],[-1,-1,[]],[[3,5],[[13,[[12,[10,11]]]]]],0,[[],5],[-1,-2,[],[]],[[3,14],6],0,[[3,14,14,5],2],[[3,10],2],[[1,1],[[13,[15]]]],0,[[3,11],[[12,[2,1]]]],[-1,-2,[],[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[17,5],[[12,[18,1]]]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[17,17],[10,10],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[17,17],15],[[10,10],15],0,[17,5],[[],17],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[-1,[[12,[17]]],19],[-1,[[12,[10]]],19],[5,2],[5,2],[[17,17],6],[[10,10],6],[[17,7],8],[[17,7],8],[[10,7],8],[[10,7],8],[-1,-1,[]],[-1,-1,[]],[[17,5],[[13,[[12,[10,11]]]]]],[[17,-1],2,20],[[10,-1],2,20],[[],5],[[],5],[-1,-2,[],[]],[-1,-2,[],[]],[[17,14],6],[[[21,[10]]],17],[[17,10],2],[[17,17],[[13,[15]]]],[[10,10],[[13,[15]]]],[-1,10,22],[[-1,23],10,22],[[17,-1],12,24],[[10,-1],12,24],[[25,-1],10,22],[[17,11],[[12,[2,1]]]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,4,[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[26,4,5],25],[-1,-2,[],[]],[-1,-2,[],[]],[26,26],[[-1,-2],2,[],[]],[[],26],[5,-1,[]],[5,-1,[]],[-1,[[12,[26]]],19],[5,2],[[26,7],8],[[26,7],8],[-1,-1,[]],[[26,14],[[13,[[2,[25,5,5]]]]]],[[26,14],[[13,[25]]]],[[26,14],[[13,[5]]]],[26,5],[[],5],[-1,-2,[],[]],[[],26],[[26,25],[[12,[25,1]]]],[[26,-1],12,24],[-1,-2,[],[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[25,25],[[-1,-2],2,[],[]],[[25,25],15],[5,-1,[]],[25,25],[5,-1,[]],[-1,[[12,[25]]],19],[5,2],[[25,25],6],[[25,7],8],[[25,7],8],[-1,-1,[]],[[25,-1],2,20],[[],5],[-1,-2,[],[]],[[25,27],25],[[25,25],[[13,[15]]]],[[25,-1],12,24],[-1,-2,[],[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[28,5],[[12,[29,1]]]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[28,28],[11,11],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],0,[28,5],[[],28],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[-1,[[12,[28]]],19],[-1,[[12,[11]]],19],[5,2],[5,2],[[28,28],6],[[11,11],6],[[28,7],8],[[28,7],8],[[11,7],8],[[11,7],8],[-1,-1,[]],[17,28],[-1,-1,[]],[[28,5],[[13,[[12,[10,11]]]]]],[[],5],[[],5],[-1,-2,[],[]],[-1,-2,[],[]],[[28,14],6],[[[21,[11]]],28],[[28,10],2],[[28,28],[[13,[15]]]],[[11,11],[[13,[15]]]],[[28,-1],12,24],[[11,-1],12,24],[[28,11],[[12,[2,1]]]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,4,[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[-1,[13,[14]],6,6],[[12,[30,4]]],22],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[31,-1],-2,[[32,[31]]],[]],[[30,-1],30,[[32,[30]]]],[[31,-1],2,[[32,[31]]]],[[33,34,-1,35],[[12,[2,36]]],22],[[34,33],[[12,[2,36]]]],[[[21,[37]]],37],[[30,-1],30,[[32,[30]]]],[[36,38],36],[[35,38],35],[[30,-1],30,[[32,[38]]]],[[35,[21,[30]]],30],[[30,[21,[30]]],30],[[34,[21,[34]]],34],[[30,[39,[37]],34,33],[[12,[6,36]]]],0,0,[[35,33],[[12,[6,36]]]],[[35,33],[[12,[40,36]]]],[[35,33],[[12,[41,36]]]],[[35,33],[[12,[42,36]]]],[[35,33],[[12,[4,36]]]],[[35,34],35],[[30,34],30],[[30,-1,-2],30,22,[[32,[30]]]],[[30,-1,-2],30,22,[[32,[30]]]],[[30,-1],30,[[32,[30]]]],[[30,-1],30,[[32,[30]]]],[[30,-1],30,[[32,[30]]]],[30,30],[[38,38],-1,[]],[[30,-1],30,[[32,[30]]]],[[38,38],2],[[30,-1],30,[[32,[30]]]],0,0,[6,37],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[[43,34,34,33],[[12,[6,36]]]],[[44,34,33],[[12,[6,36]]]],[[45,34,34,33],[[12,[6,36]]]],[[46,34,34,34,33],[[12,[6,36]]]],[[47,34,34,33],[[12,[6,36]]]],[[48,34,33],[[12,[6,36]]]],[[49,34,34,33],[[12,[6,36]]]],[[50,34,34,33],[[12,[6,36]]]],[[51,34,34,33],[[12,[6,36]]]],[[52,34,34,33],[[12,[6,36]]]],[[53,34,34,33],[[12,[6,36]]]],[[54,34,33],[[12,[6,36]]]],[[55,34,34,33],[[12,[6,36]]]],[[56,34,34,33],[[12,[6,36]]]],[[57,34,34,33],[[12,[6,36]]]],[[58,34,33],[[12,[6,36]]]],[[59,34,33],[[12,[6,36]]]],[[60,34,34,33],[[12,[6,36]]]],[[61,34,34,33],[[12,[6,36]]]],[[62,34,33],[[12,[6,36]]]],[[63,34,33],[[12,[6,36]]]],[[64,34,33],[[12,[6,36]]]],[[65,34,33],[[12,[6,36]]]],[[66,34,33],[[12,[6,36]]]],[[43,30,30,33],[[12,[6,36]]]],[[43,30,30,33],[[12,[6,36]]]],[[44,30,33],[[12,[6,36]]]],[[44,30,33],[[12,[6,36]]]],[[45,30,30,33],[[12,[6,36]]]],[[45,30,30,33],[[12,[6,36]]]],[[46,30,30,30,33],[[12,[6,36]]]],[[46,30,30,30,33],[[12,[6,36]]]],[[34,34,33],[[12,[6,36]]]],[[67,67],6],[[34,34,33],[[12,[6,36]]]],[38,38],[33,33],[36,36],[35,35],[31,31],[30,30],[47,47],[48,48],[49,49],[50,50],[51,51],[52,52],[53,53],[54,54],[55,55],[56,56],[57,57],[58,58],[59,59],[60,60],[61,61],[62,62],[63,63],[64,64],[65,65],[66,66],[37,37],[68,68],[69,69],[70,70],[71,71],[72,72],[67,67],[34,34],[43,[[73,[43]]]],[44,[[73,[44]]]],[45,[[73,[45]]]],[46,[[73,[46]]]],[47,[[73,[45]]]],[48,[[73,[44]]]],[49,[[73,[45]]]],[50,[[73,[43]]]],[51,[[73,[45]]]],[52,[[73,[45]]]],[53,[[73,[45]]]],[54,[[73,[44]]]],[55,[[73,[45]]]],[56,[[73,[45]]]],[57,[[73,[45]]]],[58,[[73,[44]]]],[59,[[73,[44]]]],[60,[[73,[45]]]],[61,[[73,[45]]]],[62,[[73,[44]]]],[63,[[73,[44]]]],[64,[[73,[44]]]],[65,[[73,[44]]]],[66,[[73,[44]]]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[43,43],15],[[44,44],15],[[45,45],15],[[46,46],15],[[38,38],15],[[47,47],15],[[48,48],15],[[51,51],15],[[52,52],15],[[53,53],15],[[54,54],15],[[55,55],15],[[56,56],15],[[57,57],15],[[58,58],15],[[59,59],15],[[60,60],15],[[63,63],15],[[64,64],15],[[65,65],15],[[66,66],15],[[67,67],15],[74,[[12,[[12,[17,28]],36]]]],[74,[[12,[[12,[17,28]],36]]]],[[43,30,30,33,3],[[12,[2,36]]]],[[43,30,30,33,3],[[12,[2,36]]]],[[44,30,33,3],[[12,[2,36]]]],[[44,30,33,3],[[12,[2,36]]]],[[45,30,30,33,3],[[12,[2,36]]]],[[45,30,30,33,3],[[12,[2,36]]]],[[46,30,30,30,33,3],[[12,[2,36]]]],[[46,30,30,30,33,3],[[12,[2,36]]]],[[47,30,30,33,3],[[12,[2,36]]]],[[49,30,30,33,3],[[12,[2,36]]]],[[50,30,30,33,3],[[12,[2,36]]]],[[74,33,3],[[12,[2,36]]]],[[35,33,3],[[12,[2,36]]]],[[30,33,3],[[12,[2,36]]]],[[68,33,3],[[12,[2,36]]]],[[69,33,3],[[12,[2,36]]]],[[70,33,3],[[12,[2,36]]]],[[71,33,3],[[12,[2,36]]]],[[43,34,34,33,3],[[12,[2,36]]]],[[44,34,33,3],[[12,[2,36]]]],[[45,34,34,33,3],[[12,[2,36]]]],[[46,34,34,34,33,3],[[12,[2,36]]]],[[47,34,34,33,3],[[12,[2,36]]]],[[48,34,33,3],[[12,[2,36]]]],[[49,34,34,33,3],[[12,[2,36]]]],[[50,34,34,33,3],[[12,[2,36]]]],[[51,34,34,33,3],[[12,[2,36]]]],[[52,34,34,33,3],[[12,[2,36]]]],[[53,34,34,33,3],[[12,[2,36]]]],[[54,34,33,3],[[12,[2,36]]]],[[55,34,34,33,3],[[12,[2,36]]]],[[56,34,34,33,3],[[12,[2,36]]]],[[57,34,34,33,3],[[12,[2,36]]]],[[58,34,33,3],[[12,[2,36]]]],[[59,34,33,3],[[12,[2,36]]]],[[60,34,34,33,3],[[12,[2,36]]]],[[61,34,34,33,3],[[12,[2,36]]]],[[62,34,33,3],[[12,[2,36]]]],[[63,34,33,3],[[12,[2,36]]]],[[64,34,33,3],[[12,[2,36]]]],[[65,34,33,3],[[12,[2,36]]]],[[66,34,33,3],[[12,[2,36]]]],[[34,14],6],[[25,34,33,3],[[12,[2,36]]]],[[37,30,34,33],[[12,[2,36]]]],[[],33],[[],67],[[33,[21,[[2,[4,34]]]]],2],[[33,-1,67,34,6],[[12,[27,36]]],22],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[30,30],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[[30,-1],30,[[32,[30]]]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[-1,[[12,[38]]],19],[-1,[[12,[35]]],19],[-1,[[12,[31]]],19],[-1,[[12,[30]]],19],[-1,[[12,[37]]],19],[-1,[[12,[68]]],19],[-1,[[12,[69]]],19],[-1,[[12,[70]]],19],[-1,[[12,[71]]],19],[-1,[[12,[72]]],19],[-1,[[12,[67]]],19],[-1,[[12,[34]]],19],[[43,30,30],4],[[43,30,30],4],[[44,30],4],[[44,30],4],[[45,30,30],4],[[45,30,30],4],[[46,30,30,30],4],[[46,30,30,30],4],[[25,34,33,3],[[12,[2,36]]]],[[30,-1],30,[[32,[30]]]],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[[43,43],6],[[44,44],6],[[45,45],6],[[46,46],6],[[38,38],6],[[35,35],6],[[31,31],6],[[30,30],6],[[30,-1],30,[[32,[30]]]],[[47,47],6],[[48,48],6],[[51,51],6],[[52,52],6],[[53,53],6],[[54,54],6],[[55,55],6],[[56,56],6],[[57,57],6],[[58,58],6],[[59,59],6],[[60,60],6],[[63,63],6],[[64,64],6],[[65,65],6],[[66,66],6],[[37,37],6],[[68,68],6],[[69,69],6],[[70,70],6],[[71,71],6],[[72,72],6],[[67,67],6],[[34,34],6],[[35,35,33],6],[[34,34,33],[[12,[6,36]]]],[[43,35,35,33],[[12,[35,36]]]],[[44,35,33],[[12,[35,36]]]],[[45,35,35,33],[[12,[35,36]]]],[[46,35,35,35,33],[[12,[35,36]]]],[[35,33],[[12,[35,36]]]],[[47,35,35,33],[[12,[35,36]]]],[[48,35,33],[[12,[35,36]]]],[[49,35,35,33],[[12,[35,36]]]],[[50,35,35,33],[[12,[35,36]]]],[[51,35,35,33],[[12,[35,36]]]],[[52,35,35,33],[[12,[35,36]]]],[[53,35,35,33],[[12,[35,36]]]],[[54,35,33],[[12,[35,36]]]],[[55,35,35,33],[[12,[35,36]]]],[[56,35,35,33],[[12,[35,36]]]],[[57,35,35,33],[[12,[35,36]]]],[[58,35,33],[[12,[35,36]]]],[[59,35,33],[[12,[35,36]]]],[[60,35,35,33],[[12,[35,36]]]],[[61,35,35,33],[[12,[35,36]]]],[[62,35,33],[[12,[35,36]]]],[[63,35,33],[[12,[35,36]]]],[[64,35,33],[[12,[35,36]]]],[[65,35,33],[[12,[35,36]]]],[[66,35,33],[[12,[35,36]]]],[[35,35],35],[[30,35],30],[41,37],[[38,7],8],[[33,7],8],[[33,7],8],[[36,7],8],[[36,7],8],[[35,7],8],[[35,7],8],[[31,7],8],[[31,7],8],[[30,7],8],[[30,7],8],[[47,7],8],[[47,7],8],[[48,7],8],[[48,7],8],[[49,7],8],[[49,7],8],[[50,7],8],[[50,7],8],[[51,7],8],[[51,7],8],[[52,7],8],[[52,7],8],[[53,7],8],[[53,7],8],[[54,7],8],[[54,7],8],[[55,7],8],[[55,7],8],[[56,7],8],[[56,7],8],[[57,7],8],[[57,7],8],[[58,7],8],[[58,7],8],[[59,7],8],[[59,7],8],[[60,7],8],[[60,7],8],[[61,7],8],[[61,7],8],[[62,7],8],[[62,7],8],[[63,7],8],[[63,7],8],[[64,7],8],[[64,7],8],[[65,7],8],[[65,7],8],[[66,7],8],[[66,7],8],[[37,7],8],[[37,7],8],[[68,7],8],[[68,7],8],[[69,7],8],[[69,7],8],[[70,7],8],[[70,7],8],[[71,7],8],[[71,7],8],[[72,7],8],[[72,7],8],[[67,7],8],[[67,7],8],[[34,7],8],[[34,7],8],[75,38],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[1,36],[-1,-1,[]],[72,35],[71,35],[34,35],[[[2,[4,35]]],31],[-1,-1,[]],[[[2,[4,72]]],31],[[[2,[14,30]]],31],[[[2,[14,71]]],31],[[[2,[14,72]]],31],[[[2,[4,70]]],31],[[[2,[4,67,34,30]]],31],[[[2,[4,67,30]]],31],[[[21,[-1]]],31,[[32,[31]]]],[[[2,[14,67,34,30]]],31],[[[2,[4,71]]],31],[[[2,[14,67,30]]],31],[[[76,[-1,-2]]],31,[],[]],[[[2,[14,67,[13,[34]],30]]],31],[[[73,[31]]],31],[[[2,[4,30]]],31],[[[2,[4,67,[13,[34]],30]]],31],[[[2,[37,30]]],31],[[[2,[4,34]]],31],[[[2,[14,70]]],31],[[[2,[14,35]]],31],[[[2,[14,34]]],31],[35,30],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[6,67],[-1,-1,[]],[-1,-1,[]],[[71,[21,[[2,[4,[13,[34]]]]]]],72],[[30,-1],30,[[32,[30]]]],[[33,34],[[21,[[2,[4,35]]]]]],[71,[[39,[[2,[4,67,34]]]]]],[[33,34,14],[[13,[[2,[35,34]]]]]],[[37,30,34,33],[[12,[[77,[4,[2,[67,34]]]],36]]]],[71,30],[[37,30,30,33],[[12,[34,36]]]],[71,[[13,[14]]]],[71,14],[[30,33],[[12,[[13,[67]],36]]]],[[34,34,[77,[4,[2,[34,[13,[34]]]]]],[78,[4]],33],[[12,[2,36]]]],[72,14],[71,34],[[34,33],[[13,[67]]]],[[79,33],[[12,[5,36]]]],[[79,33],[[12,[5,36]]]],[[79,33,5],[[12,[5,36]]]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[-1,33,5],[[12,[5,36]]],[]],[[34,33,5],[[12,[5,36]]]],[[34,33],[[21,[[2,[4,[13,[34]]]]]]]],[[80,33],[[12,[34,36]]]],[[80,33],[[12,[34,36]]]],[[80,33,5],[[12,[34,36]]]],[[35,33,5],[[12,[34,36]]]],[[30,33,5],[[12,[34,36]]]],[[68,33,5],[[12,[34,36]]]],[[69,33,5],[[12,[34,36]]]],[[70,33,5],[[12,[34,36]]]],[[71,33,5],[[12,[34,36]]]],[[72,33,5],[[12,[34,36]]]],[[33,34,14],[[13,[34]]]],[72,[[21,[[2,[4,[13,[34]]]]]]]],[[30,-1],30,[[32,[30]]]],[[30,-1],30,[[32,[31]]]],[[33,34,14],6],[[34,34,33],[[12,[6,36]]]],[38,6],[[38,-1],2,20],[[35,-1],2,20],[[31,-1],2,20],[[30,-1],2,20],[[47,-1],2,20],[[48,-1],2,20],[[51,-1],2,20],[[52,-1],2,20],[[53,-1],2,20],[[54,-1],2,20],[[55,-1],2,20],[[56,-1],2,20],[[57,-1],2,20],[[58,-1],2,20],[[59,-1],2,20],[[60,-1],2,20],[[63,-1],2,20],[[64,-1],2,20],[[65,-1],2,20],[[66,-1],2,20],[[37,-1],2,20],[[68,-1],2,20],[[69,-1],2,20],[[70,-1],2,20],[[71,-1],2,20],[[72,-1],2,20],[[67,-1],2,20],[[34,-1],2,20],[[30,-1],30,[[32,[30]]]],[[37,30,30,30,33],[[12,[30,36]]]],[[30,-1,-2],30,[[32,[30]]],[[32,[30]]]],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[42,37],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[34,6],[38,6],[34,6],[34,6],[67,6],[38,6],[[37,30,34,33],[[12,[6,36]]]],[38,6],[[30,33],[[12,[6,36]]]],[[34,34,33],[[12,[6,36]]]],[67,6],[38,6],[34,6],[[34,33],[[12,[6,36]]]],[[34,[78,[4]],33],[[12,[6,36]]]],[[34,33],[[12,[6,36]]]],[34,6],[38,6],[[30,-1],30,[[32,[30]]]],[[14,34,34],34],[[-1,35,-2],30,22,[[32,[30]]]],[[[21,[[2,[14,35]]]],-1],30,[[32,[30]]]],[[-1,71,-2],30,22,[[32,[30]]]],[[[76,[14,71]],-1],30,[[32,[30]]]],[[-1,34,-2],30,22,[[32,[30]]]],[[[21,[[2,[14,34]]]],-1],30,[[32,[30]]]],[[-1,-2,[13,[34]],-3,-4],30,22,[[32,[67]]],[[32,[30]]],[[32,[30]]]],[[[21,[[2,[14,67,[13,[34]],30]]]],-1],30,[[32,[30]]]],[38,[[13,[75]]]],[[30,-1],30,[[32,[30]]]],[-1,31,[[32,[[21,[31]]]]]],[[30,[39,[[2,[37,30]]]],33],[[12,[30,36]]]],[[-1,-2],31,22,[[32,[[21,[31]]]]]],[[35,[21,[34]]],35],[[72,[21,[34]],33],[[12,[71,36]]]],[[30,-1],30,[[32,[30]]]],[43,4],[43,4],[44,4],[44,4],[45,4],[45,4],[46,4],[46,4],0,0,[30,30],[[30,-1],30,[[32,[30]]]],[-1,50,45],[[4,[21,[34]],34],70],[[[13,[4]],[21,[[2,[4,67,34]]]],34,-1],71,[[32,[30]]]],[[4,[21,[[2,[4,[13,[34]]]]]],[21,[[2,[4,67,34]]]],34,-1],72,[[32,[30]]]],[30,30],[[30,-1],30,[[32,[30]]]],[[43,43],[[13,[15]]]],[[44,44],[[13,[15]]]],[[45,45],[[13,[15]]]],[[46,46],[[13,[15]]]],[[38,38],[[13,[15]]]],[[47,47],[[13,[15]]]],[[48,48],[[13,[15]]]],[[51,51],[[13,[15]]]],[[52,52],[[13,[15]]]],[[53,53],[[13,[15]]]],[[54,54],[[13,[15]]]],[[55,55],[[13,[15]]]],[[56,56],[[13,[15]]]],[[57,57],[[13,[15]]]],[[58,58],[[13,[15]]]],[[59,59],[[13,[15]]]],[[60,60],[[13,[15]]]],[[63,63],[[13,[15]]]],[[64,64],[[13,[15]]]],[[65,65],[[13,[15]]]],[[66,66],[[13,[15]]]],[[67,67],[[13,[15]]]],[[34,33,[77,[[2,[34,[21,[34]]]],34]],6],[[12,[34,36]]]],[37,37],[[30,-1],30,[[32,[30]]]],[30,30],[30,30],[[[13,[4]],[21,[[2,[4,67,34]]]],34,-1],35,[[32,[30]]]],[[71,3],2],[[30,-1],30,[[32,[67]]]],[[30,-1],30,[[32,[30]]]],0,0,[[43,30,30,33],[[12,[34,36]]]],[[43,30,30,33],[[12,[34,36]]]],[[44,30,33],[[12,[34,36]]]],[[44,30,33],[[12,[34,36]]]],[[45,30,30,33],[[12,[34,36]]]],[[45,30,30,33],[[12,[34,36]]]],[[46,30,30,30,33],[[12,[34,36]]]],[[46,30,30,30,33],[[12,[34,36]]]],[[47,30,30,33],[[12,[34,36]]]],[[48,30,33],[[12,[34,36]]]],[[49,30,30,33],[[12,[34,36]]]],[[50,30,30,33],[[12,[34,36]]]],[[51,30,30,33],[[12,[34,36]]]],[[52,30,30,33],[[12,[34,36]]]],[[53,30,30,33],[[12,[34,36]]]],[[54,30,33],[[12,[34,36]]]],[[55,30,30,33],[[12,[34,36]]]],[[56,30,30,33],[[12,[34,36]]]],[[57,30,30,33],[[12,[34,36]]]],[[58,30,33],[[12,[34,36]]]],[[59,30,33],[[12,[34,36]]]],[[60,30,30,33],[[12,[34,36]]]],[[61,30,30,33],[[12,[34,36]]]],[[62,30,33],[[12,[34,36]]]],[[63,30,33],[[12,[34,36]]]],[[64,30,33],[[12,[34,36]]]],[[65,30,33],[[12,[34,36]]]],[[66,30,33],[[12,[34,36]]]],[[38,-1],12,24],[[35,-1],12,24],[[31,-1],12,24],[[30,-1],12,24],[[37,-1],12,24],[[68,-1],12,24],[[69,-1],12,24],[[70,-1],12,24],[[71,-1],12,24],[[72,-1],12,24],[[67,-1],12,24],[[34,-1],12,24],[[71,-1],2,22],[[81,33],[[12,[81,36]]]],[[81,33,5],[[12,[81,36]]]],[[35,33,5],[[12,[35,36]]]],[[34,33,5],[[12,[34,36]]]],[[34,33,6],[[12,[34,36]]]],[[34,33,6],[[12,[34,36]]]],[[34,33,6],[[12,[35,36]]]],[[34,33,6],[[12,[34,36]]]],[[34,33,6],[[12,[34,36]]]],[[34,33,34,-1,6],[[12,[34,36]]],[[83,[34,33],[[82,[[12,[6,36]]]]]]]],[[34,33,6],[[12,[34,36]]]],[[34,33,6],[[12,[34,36]]]],[[34,33],[[12,[34,36]]]],[[34,33,6],[[12,[34,36]]]],[30,30],[[34,33],34],[[[76,[4,37]]],37],[[[76,[14,30]]],30],[[30,-1],30,[[32,[30]]]],[[80,14,34],2],[[35,14,34],2],[[30,14,34],2],[[68,14,34],2],[[69,14,34],2],[[70,14,34],2],[[71,14,34],2],[[72,14,34],2],[[34,14,34],34],[[80,[39,[4]],[39,[34]]],2],[[80,[39,[4]],[39,[34]]],2],[[-1,-2],37,[[32,[67]]],22],[[35,[21,[[2,[4,[13,[34]]]]]]],35],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[[30,33],[[12,[30,36]]]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[[[21,[37]]],37],[[84,33],[[12,[2,36]]]],[[43,30,30,33],[[12,[2,36]]]],[[43,30,30,33],[[12,[2,36]]]],[[44,30,33],[[12,[2,36]]]],[[44,30,33],[[12,[2,36]]]],[[45,30,30,33],[[12,[2,36]]]],[[45,30,30,33],[[12,[2,36]]]],[[46,30,30,30,33],[[12,[2,36]]]],[[46,30,30,30,33],[[12,[2,36]]]],[[35,33],[[12,[2,36]]]],[[31,33],[[12,[2,36]]]],[[30,33],[[12,[2,36]]]],[[37,30,30,33],[[12,[2,36]]]],[[68,33],[[12,[2,36]]]],[[69,33],[[12,[2,36]]]],[[70,33],[[12,[2,36]]]],[[71,33],[[12,[2,36]]]],[[72,33],[[12,[2,36]]]],[[34,33],[[12,[2,36]]]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[[30,-1],30,22],[-1,35,22],[-1,30,22],[[[39,[4]],4],[[13,[5]]]],[[30,-1],30,[[32,[30]]]],[[],37],[[35,-1],35,[[32,[31]]]],[[30,-1],30,[[32,[31]]]],[[71,-1],71,[[32,[31]]]],[[72,-1],72,[[32,[31]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[75,75],[[-1,-2],2,[],[]],[[75,75],15],0,[5,-1,[]],[5,-1,[]],[-1,[[12,[75]]],19],[5,2],[[75,75],6],0,[[75,7],8],[-1,-1,[]],[[75,14],4],[[75,-1],2,20],[[],5],[-1,-2,[],[]],0,0,0,[-1,[[12,[[12,[17,28]],4]]],22],[[-1,[13,[14]]],[[12,[30,4]]],22],[[-1,[13,[14]]],[[12,[30,4]]],22],[-1,[[12,[30,4]]],22],[-1,[[12,[[12,[18,29]],4]]],22],[[75,75],[[13,[15]]]],[[75,-1],12,24],[-1,-2,[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[85,85],[[-1,-2],2,[],[]],[[85,85],15],[5,-1,[]],[5,-1,[]],[-1,[[12,[85]]],19],[5,2],[[85,85],6],[[85,7],8],[[85,7],8],[-1,-1,[]],[[85,-1],2,20],[[],5],0,[-1,-2,[],[]],0,[[4,5,5],85],0,[[85,85],[[13,[15]]]],[[85,-1],12,24],[-1,-2,[],[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],0,0,[[],86],[87,87],[88,88],[89,89],[90,90],[91,91],[92,92],[86,86],[23,23],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[87,87],15],[[88,88],15],[[89,89],15],[[90,90],15],[[91,91],15],[[92,92],15],[[86,86],15],[[23,23],15],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[-1,[[12,[87]]],19],[-1,[[12,[88]]],19],[-1,[[12,[89]]],19],[-1,[[12,[90]]],19],[-1,[[12,[91]]],19],[-1,[[12,[92]]],19],[-1,[[12,[86]]],19],[-1,[[12,[23]]],19],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[[87,87],6],[[88,88],6],[[89,89],6],[[90,90],6],[[91,91],6],[[92,92],6],[[86,86],6],[[23,23],6],[[87,7],8],[[87,7],8],[[88,7],8],[[88,7],8],[[89,7],8],[[89,7],8],[[90,7],8],[[90,7],8],[[91,7],8],[[91,7],8],[[92,7],8],[[92,7],8],[[86,7],8],[[86,7],8],[[23,7],8],[[23,7],8],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[[87,-1],2,20],[[88,-1],2,20],[[89,-1],2,20],[[90,-1],2,20],[[91,-1],2,20],[[92,-1],2,20],[[86,-1],2,20],[[23,-1],2,20],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],0,0,[[90,5],86],[[91,5],23],[[87,87],[[13,[15]]]],[[88,88],[[13,[15]]]],[[89,89],[[13,[15]]]],[[90,90],[[13,[15]]]],[[91,91],[[13,[15]]]],[[92,92],[[13,[15]]]],[[86,86],[[13,[15]]]],[[23,23],[[13,[15]]]],[[],86],[[87,-1],12,24],[[88,-1],12,24],[[89,-1],12,24],[[90,-1],12,24],[[91,-1],12,24],[[92,-1],12,24],[[86,-1],12,24],[[23,-1],12,24],[[],23],[[],23],[[],23],[[],86],[[],86],[[],86],[[],23],[[],23],[[],23],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],0,0,[[93,18],[[12,[4,4]]]],[[93,94,[21,[94]],[21,[5]],5,5],[[12,[4,4]]]],[[93,29],[[12,[4,4]]]],[[93,95,[21,[94]],[21,[5]],5,5],[[12,[4,4]]]],0,[[96,5],4],[[96,94,[13,[5]]],4],[[96,86],[[12,[4,4]]]],[96,[[13,[4]]]],[96,14],[[96,94],4],[96,[[12,[4,4]]]],[96,[[12,[4,4]]]],[[96,[21,[97]]],[[13,[4]]]],[[96,6],[[13,[4]]]],[96,[[13,[4]]]],[[96,[21,[97]]],[[13,[4]]]],[[96,6],[[13,[4]]]],[[96,23],[[12,[4,4]]]],[[96,95],[[12,[4,4]]]],[96,6],[[96,86],6],[[96,23],6],[96,14],0,[-1,-2,[],[]],[-1,-2,[],[]],[[98,5],4],[[],98],[5,-1,[]],[5,-1,[]],[5,2],[[98,94,[13,[5]]],4],[-1,-1,[]],[[98,86],[[12,[4,4]]]],[[],5],[-1,-2,[],[]],[98,14],[[98,94],4],[98,[[12,[4,4]]]],[98,[[12,[4,4]]]],[[98,[21,[97]]],[[13,[4]]]],[[98,6],[[13,[4]]]],[98,[[13,[4]]]],[[98,6],[[13,[4]]]],[[98,23],[[12,[4,4]]]],[[98,95],[[12,[4,4]]]],[98,6],[[98,86],6],[[98,23],6],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],[98,14],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[99,85],2],[42,41],[41,42],[100,2],[100,2],[100,2],[100,2],[100,2],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[100,2],[18,18],[94,94],[29,29],[95,95],[99,99],[9,9],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[-1,-2],2,[],[]],[[18,18],15],[[94,94],15],[100,[[12,[18,29]]]],[18,[[12,[18,29]]]],[29,[[12,[18,29]]]],[[100,14],2],[[],[[101,[99]]]],[[],[[102,[99]]]],[[],18],[[],29],[[],103],[[],99],[5,-1,[]],[5,-1,[]],[100,2],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,-1,[]],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[5,2],[100,2],[[18,18],6],[[94,94],6],[[29,29],6],[[95,95],6],[[9,9],6],0,[[104,85,[13,[[21,[42]]]]],[[12,[2,4]]]],[[100,85],[[12,[2,9]]]],[[103,85,[13,[[21,[42]]]]],[[12,[2,4]]]],[[99,85,[13,[[21,[42]]]]],[[12,[2,4]]]],0,[18,18],[29,29],[[18,7],8],[[94,7],8],[[94,7],8],[[29,7],8],[[95,7],8],[[95,7],8],[[103,7],8],[[99,7],8],[[9,7],8],[[9,7],8],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[18,29],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[-1,-1,[]],[[104,86],[[12,[42,4]]]],[[100,86],2],[[103,86],[[12,[42,4]]]],[[99,86],[[12,[42,4]]]],[18,[[77,[97,[21,[94]]]]]],[29,[[77,[97,[21,[95]]]]]],[18,[[21,[94]]]],[29,[[21,[95]]]],[18,[[2,[[21,[94]],[77,[97,[21,[94]]]]]]]],[29,[[2,[[21,[95]],[77,[97,[21,[95]]]]]]]],[[18,-1],2,20],[[94,-1],2,20],[100,2],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],[[],5],0,[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[100,2],[[100,5],2],[[100,27],2],[-1,[[101,[-1]]],104],[-1,[[102,[-1]]],104],[-1,103,22],[[[21,[42]]],103],[[100,94],2],[[18,94],2],[[29,94],2],0,[103,4],[103,[[21,[42]]]],[[18,18],[[13,[15]]]],[[94,94],[[13,[15]]]],[[29,29],[[13,[15]]]],[[95,95],[[13,[15]]]],[[9,9],[[13,[15]]]],[104,[[12,[42,4]]]],[100,[[12,[2,9]]]],[103,[[12,[42,4]]]],[99,[[12,[42,4]]]],[[104,42],[[12,[2,4]]]],[100,[[12,[2,9]]]],[[103,42],[[12,[2,4]]]],[[99,42],[[12,[2,4]]]],[[104,42,23],[[12,[2,4]]]],[[100,23],2],[[103,42,23],[[12,[2,4]]]],[[99,42,23],[[12,[2,4]]]],[100,2],[100,2],[100,2],[[[101,[-1]],18],[[12,[-1,4]]],104],[[[102,[-1]],29],[[12,[-1,4]]],104],[100,2],[[100,41],[[12,[2,9]]]],[[100,[21,[41]]],[[12,[2,9]]]],[[100,42],2],[[100,[21,[42]]],2],[[100,95],[[12,[2,9]]]],[[18,95],[[12,[2,9]]]],[[29,95],[[12,[2,9]]]],[[100,5],2],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,4,[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,[[12,[-2]]],[],[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[-1,16,[]],[100,2]],"c":[],"p":[[6,"Error",10],[1,"tuple"],[10,"AssemblyProgram",10],[5,"String",2653],[1,"usize"],[1,"bool"],[5,"Formatter",2654],[8,"Result",2654],[6,"Error",2349],[6,"CoreOp",65],[6,"StandardOp",416],[6,"Result",2655],[6,"Option",2656],[1,"str"],[6,"Ordering",2657],[5,"TypeId",2658],[5,"CoreProgram",65],[5,"CoreProgram",2349],[10,"Deserializer",2659],[10,"Hasher",2660],[5,"Vec",2661],[10,"ToString",2653],[5,"Output",1987],[10,"Serializer",2662],[6,"Location",376],[5,"Globals",348],[1,"isize"],[5,"StandardProgram",416],[5,"StandardProgram",2349],[6,"Expr",566],[6,"Declaration",566],[10,"Into",2663],[5,"Env",566],[6,"Type",566],[6,"ConstExpr",566],[6,"Error",566],[6,"Pattern",566],[6,"Annotation",566],[1,"slice"],[1,"char"],[1,"f64"],[1,"i64"],[10,"AssignOp",566],[10,"UnaryOp",566],[10,"BinaryOp",566],[10,"TernaryOp",566],[5,"Add",566],[5,"Negate",566],[6,"Arithmetic",566],[5,"Assign",566],[5,"BitwiseAnd",566],[5,"BitwiseNand",566],[5,"BitwiseNor",566],[5,"BitwiseNot",566],[5,"BitwiseOr",566],[5,"BitwiseXor",566],[6,"Comparison",566],[5,"Get",566],[6,"Put",566],[5,"And",566],[5,"Or",566],[5,"Not",566],[5,"New",566],[5,"Delete",566],[5,"Tag",566],[5,"Data",566],[6,"Mutability",566],[5,"CoreBuiltin",566],[5,"StandardBuiltin",566],[5,"FFIProcedure",566],[5,"Procedure",566],[5,"PolyProcedure",566],[5,"Box",2664],[10,"Compile",566],[5,"SourceCodeLocation",1924],[5,"BTreeMap",2665],[5,"HashMap",2666],[5,"HashSet",2667],[10,"GetSize",566],[10,"GetType",566],[10,"Simplify",566],[17,"Output"],[10,"Fn",2668],[10,"TypeCheck",566],[5,"FFIBinding",1959],[5,"Input",1987],[6,"Axis",1987],[6,"Direction",1987],[6,"Color",1987],[6,"InputMode",1987],[6,"OutputMode",1987],[5,"Channel",1987],[10,"CompiledTarget",2293],[6,"CoreOp",2349],[6,"StandardOp",2349],[10,"Architecture",2293],[1,"i32"],[5,"C",2319],[5,"StandardDevice",2349],[10,"VirtualMachineProgram",2349],[5,"CoreInterpreter",2349],[5,"StandardInterpreter",2349],[5,"TestingDevice",2349],[10,"Device",2349],[15,"Compare",207],[15,"IsGreater",207],[15,"IsGreaterEqual",207],[15,"IsLess",207],[15,"IsLessEqual",207],[15,"IsEqual",207],[15,"IsNotEqual",207],[15,"GetAddress",207],[15,"Move",207],[15,"Copy",207],[15,"Index",207],[15,"Add",207],[15,"Sub",207],[15,"Mul",207],[15,"Div",207],[15,"Rem",207],[15,"DivRem",207],[15,"VecAdd",207],[15,"VecSub",207],[15,"VecMul",207],[15,"VecDiv",207],[15,"VecRem",207],[15,"And",207],[15,"Or",207],[15,"VecNot",207],[15,"VecAnd",207],[15,"VecOr",207],[15,"VecInc",207],[15,"VecDec",207],[15,"LeftShift",207],[15,"LogicalRightShift",207],[15,"ArithmeticRightShift",207],[15,"VecLeftShift",207],[15,"VecLogicalRightShift",207],[15,"VecArithmeticRightShift",207],[15,"VecGez",207],[15,"VecNeg",207],[15,"VecOffset",207],[15,"VecIndex",207],[15,"PopFrom",207],[15,"Array",207],[15,"Const",207],[15,"BitwiseNand",207],[15,"BitwiseXor",207],[15,"BitwiseOr",207],[15,"BitwiseNor",207],[15,"BitwiseAnd",207],[15,"VecBitwiseAnd",207],[15,"VecBitwiseOr",207],[15,"VecBitwiseXor",207],[15,"VecBitwiseNor",207],[15,"VecBitwiseNand",207],[15,"VecBitwiseNot",207],[15,"Global",207],[15,"PushTo",207],[15,"IsGreater",510],[15,"IsLess",510],[15,"Const",510],[15,"Pow",510],[15,"Add",510],[15,"Sub",510],[15,"Mul",510],[15,"Div",510],[15,"Rem",510],[15,"VecAdd",510],[15,"VecSub",510],[15,"VecMul",510],[15,"VecDiv",510],[15,"VecRem",510],[15,"VecNeg",510],[15,"VecPow",510],[15,"VecSin",510],[15,"VecCos",510],[15,"VecTan",510],[15,"VecASin",510],[15,"VecACos",510],[15,"VecATan",510],[15,"VecGez",510],[15,"FromImport",1912],[15,"MismatchedTypes",1914],[15,"MismatchedMutability",1914],[15,"UnexpectedConstParam",1914],[15,"NonExhaustivePatterns",1914]],"b":[[45,"impl-Display-for-Error"],[46,"impl-Debug-for-Error"],[173,"impl-Debug-for-CoreProgram"],[174,"impl-Display-for-CoreProgram"],[175,"impl-Debug-for-CoreOp"],[176,"impl-Display-for-CoreOp"],[359,"impl-Display-for-Globals"],[360,"impl-Debug-for-Globals"],[402,"impl-Debug-for-Location"],[403,"impl-Display-for-Location"],[480,"impl-Display-for-StandardProgram"],[481,"impl-Debug-for-StandardProgram"],[482,"impl-Display-for-StandardOp"],[483,"impl-Debug-for-StandardOp"],[1222,"impl-PartialEq-for-Expr"],[1223,"impl-Expr"],[1279,"impl-Display-for-Env"],[1280,"impl-Debug-for-Env"],[1281,"impl-Display-for-Error"],[1282,"impl-Debug-for-Error"],[1283,"impl-Debug-for-ConstExpr"],[1284,"impl-Display-for-ConstExpr"],[1285,"impl-Debug-for-Declaration"],[1286,"impl-Display-for-Declaration"],[1287,"impl-Display-for-Expr"],[1288,"impl-Debug-for-Expr"],[1289,"impl-Debug-for-Add"],[1290,"impl-Display-for-Add"],[1291,"impl-Display-for-Negate"],[1292,"impl-Debug-for-Negate"],[1293,"impl-Display-for-Arithmetic"],[1294,"impl-Debug-for-Arithmetic"],[1295,"impl-Debug-for-Assign"],[1296,"impl-Display-for-Assign"],[1297,"impl-Display-for-BitwiseAnd"],[1298,"impl-Debug-for-BitwiseAnd"],[1299,"impl-Debug-for-BitwiseNand"],[1300,"impl-Display-for-BitwiseNand"],[1301,"impl-Display-for-BitwiseNor"],[1302,"impl-Debug-for-BitwiseNor"],[1303,"impl-Display-for-BitwiseNot"],[1304,"impl-Debug-for-BitwiseNot"],[1305,"impl-Display-for-BitwiseOr"],[1306,"impl-Debug-for-BitwiseOr"],[1307,"impl-Display-for-BitwiseXor"],[1308,"impl-Debug-for-BitwiseXor"],[1309,"impl-Display-for-Comparison"],[1310,"impl-Debug-for-Comparison"],[1311,"impl-Debug-for-Get"],[1312,"impl-Display-for-Get"],[1313,"impl-Display-for-Put"],[1314,"impl-Debug-for-Put"],[1315,"impl-Display-for-And"],[1316,"impl-Debug-for-And"],[1317,"impl-Debug-for-Or"],[1318,"impl-Display-for-Or"],[1319,"impl-Debug-for-Not"],[1320,"impl-Display-for-Not"],[1321,"impl-Debug-for-New"],[1322,"impl-Display-for-New"],[1323,"impl-Debug-for-Delete"],[1324,"impl-Display-for-Delete"],[1325,"impl-Display-for-Tag"],[1326,"impl-Debug-for-Tag"],[1327,"impl-Display-for-Data"],[1328,"impl-Debug-for-Data"],[1329,"impl-Debug-for-Pattern"],[1330,"impl-Display-for-Pattern"],[1331,"impl-Display-for-CoreBuiltin"],[1332,"impl-Debug-for-CoreBuiltin"],[1333,"impl-Display-for-StandardBuiltin"],[1334,"impl-Debug-for-StandardBuiltin"],[1335,"impl-Debug-for-FFIProcedure"],[1336,"impl-Display-for-FFIProcedure"],[1337,"impl-Debug-for-Procedure"],[1338,"impl-Display-for-Procedure"],[1339,"impl-Display-for-PolyProcedure"],[1340,"impl-Debug-for-PolyProcedure"],[1341,"impl-Debug-for-Mutability"],[1342,"impl-Display-for-Mutability"],[1343,"impl-Display-for-Type"],[1344,"impl-Debug-for-Type"],[1351,"impl-From%3CPolyProcedure%3E-for-ConstExpr"],[1352,"impl-From%3CProcedure%3E-for-ConstExpr"],[1353,"impl-From%3CType%3E-for-ConstExpr"],[1354,"impl-From%3C(String,+ConstExpr)%3E-for-Declaration"],[1356,"impl-From%3C(String,+PolyProcedure)%3E-for-Declaration"],[1357,"impl-From%3C(%26str,+Expr)%3E-for-Declaration"],[1358,"impl-From%3C(%26str,+Procedure)%3E-for-Declaration"],[1359,"impl-From%3C(%26str,+PolyProcedure)%3E-for-Declaration"],[1360,"impl-From%3C(String,+FFIProcedure)%3E-for-Declaration"],[1361,"impl-From%3C(String,+Mutability,+Type,+Expr)%3E-for-Declaration"],[1362,"impl-From%3C(String,+Mutability,+Expr)%3E-for-Declaration"],[1363,"impl-From%3CVec%3CT%3E%3E-for-Declaration"],[1364,"impl-From%3C(%26str,+Mutability,+Type,+Expr)%3E-for-Declaration"],[1365,"impl-From%3C(String,+Procedure)%3E-for-Declaration"],[1366,"impl-From%3C(%26str,+Mutability,+Expr)%3E-for-Declaration"],[1367,"impl-From%3CBTreeMap%3CK,+V%3E%3E-for-Declaration"],[1368,"impl-From%3C(%26str,+Mutability,+Option%3CType%3E,+Expr)%3E-for-Declaration"],[1369,"impl-From%3CBox%3CDeclaration%3E%3E-for-Declaration"],[1370,"impl-From%3C(String,+Expr)%3E-for-Declaration"],[1371,"impl-From%3C(String,+Mutability,+Option%3CType%3E,+Expr)%3E-for-Declaration"],[1372,"impl-From%3C(Pattern,+Expr)%3E-for-Declaration"],[1373,"impl-From%3C(String,+Type)%3E-for-Declaration"],[1374,"impl-From%3C(%26str,+FFIProcedure)%3E-for-Declaration"],[1375,"impl-From%3C(%26str,+ConstExpr)%3E-for-Declaration"],[1376,"impl-From%3C(%26str,+Type)%3E-for-Declaration"],[1970,"impl-Debug-for-FFIBinding"],[1971,"impl-Display-for-FFIBinding"],[2175,"impl-Display-for-Axis"],[2176,"impl-Debug-for-Axis"],[2177,"impl-Display-for-Direction"],[2178,"impl-Debug-for-Direction"],[2179,"impl-Debug-for-Color"],[2180,"impl-Display-for-Color"],[2181,"impl-Display-for-InputMode"],[2182,"impl-Debug-for-InputMode"],[2183,"impl-Debug-for-OutputMode"],[2184,"impl-Display-for-OutputMode"],[2185,"impl-Debug-for-Channel"],[2186,"impl-Display-for-Channel"],[2187,"impl-Debug-for-Input"],[2188,"impl-Display-for-Input"],[2189,"impl-Debug-for-Output"],[2190,"impl-Display-for-Output"],[2519,"impl-Display-for-CoreOp"],[2520,"impl-Debug-for-CoreOp"],[2522,"impl-Display-for-StandardOp"],[2523,"impl-Debug-for-StandardOp"],[2526,"impl-Debug-for-Error"],[2527,"impl-Display-for-Error"]]}]\ ]')); if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; else if (window.initSearch) window.initSearch(searchIndex); diff --git a/docs/src/sage/frontend/parse.rs.html b/docs/src/sage/frontend/parse.rs.html index be93c3e1..9a0994b8 100644 --- a/docs/src/sage/frontend/parse.rs.html +++ b/docs/src/sage/frontend/parse.rs.html @@ -4864,63 +4864,6 @@ 4863 4864 4865 -4866 -4867 -4868 -4869 -4870 -4871 -4872 -4873 -4874 -4875 -4876 -4877 -4878 -4879 -4880 -4881 -4882 -4883 -4884 -4885 -4886 -4887 -4888 -4889 -4890 -4891 -4892 -4893 -4894 -4895 -4896 -4897 -4898 -4899 -4900 -4901 -4902 -4903 -4904 -4905 -4906 -4907 -4908 -4909 -4910 -4911 -4912 -4913 -4914 -4915 -4916 -4917 -4918 -4919 -4920 -4921 -4922
use log::{error, trace};
 use nom::{
     branch::alt,
@@ -5200,15 +5143,7 @@
         Expr::None
     });
 
-    // env.bind_builtin("do", |env, exprs| {
-    //     let mut result = Expr::default();
-    //     for e in exprs {
-    //         result = env.eval(e.clone());
-    //     }
-    //     result
-    // });
-
-    env.bind_lazy_builtin("do", |_env, exprs| Expr::Many(Vec::from(exprs)));
+    env.bind_lazy_builtin("do", |_env, exprs| Expr::Many(Vec::from(exprs)));
 
     env.bind_builtin("sqrt", |env, expr| {
         let e = env.eval(expr[0].clone());
@@ -6288,11 +6223,7 @@
 fn parse_impl_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
     input: &'a str,
 ) -> IResult<&'a str, Statement, E> {
-    // "impl" <name: Symbol> <args: Tuple<(<(<Symbol> ":")?> <Type>)>> <body: Block> => {
-    //     let args: Vec<_> = args.into_iter().map(|(_name, ty)| ty).collect();
-    //     Statement::Declaration(Declaration::Impl(name, args, body))
-    // },
-    let (input, _) = tag("impl")(input)?;
+    let (input, _) = tag("impl")(input)?;
 
     let (input, ty) = cut(parse_type)(input)?;
 
@@ -6320,8 +6251,7 @@
     input: &'a str,
     ty: &Type,
 ) -> IResult<&'a str, (String, ConstExpr), E> {
-    // let (input, _) = whitespace(input)?;
-    if let Ok((input, method)) = parse_impl_method::<E>(input, ty) {
+    if let Ok((input, method)) = parse_impl_method::<E>(input, ty) {
         return Ok((input, method));
     }
 
@@ -6345,16 +6275,8 @@
     let (input, (params, ret)) = cut(parse_fun_params)(input)?;
     let (input, _) = whitespace(input)?;
     let (input, body) = cut(parse_block)(input)?;
-    // Ok((input, (name.to_owned(), ConstExpr::Proc(Procedure::new(name, params, ret, body))))
-
-    // lazy_static! {
-    //     static ref IMPL_FUN_COUNTER: RwLock<usize> = RwLock::new(0);
-    // }
-    // let mut count = *IMPL_FUN_COUNTER.read().unwrap();
-    // count += 1;
-    // *IMPL_FUN_COUNTER.write().unwrap() = count;
 
-    if let Some(args) = template_args {
+    if let Some(args) = template_args {
         Ok((
             input,
             (
@@ -6400,11 +6322,7 @@
     input: &'a str,
     ty: &Type,
 ) -> IResult<&'a str, (String, ConstExpr), E> {
-    // "fun" <name: Symbol> <args: Tuple<(<(<Symbol> ":")?> <Type>)>> ":" <ret: Type> <body: Block> => {
-    //     let args: Vec<_> = args.into_iter().map(|(_name, ty)| ty).collect();
-    //     Statement::Declaration(Declaration::Proc(name.clone(), Procedure::new(name, args, ret, body)))
-    // },
-    trace!("Parsing impl method");
+    trace!("Parsing impl method");
     let (input, _) = tag("fun")(input)?;
     trace!("Parsing method");
     let (input, _) = whitespace(input)?;
@@ -6416,33 +6334,61 @@
     let (input, template_args) = cut(opt(parse_type_params))(input)?;
     trace!("Parsed template args: {template_args:#?}");
     // Get the function parameters with mutability
-    let (input, (params, ret)) = parse_method_params(input, ty)?;
-    trace!("Parsed method parameters: {params:#?}, {ret:#?}");
-    let (input, _) = whitespace(input)?;
-    let (input, body) = cut(parse_block)(input)?;
-    // Ok((input, Statement::Declaration(Declaration::Proc(name.to_owned(), Procedure::new(Some(name.to_owned()), params, ret, body))))
-    if let Some(args) = template_args {
-        Ok((
-            input,
-            (
-                name.to_owned(),
-                ConstExpr::PolyProc(PolyProcedure::new(
+    if let Ok((input, (params, ret))) = parse_method_params::<E>(input, ty) {
+        trace!("Parsed method parameters: {params:#?}, {ret:#?}");
+        let (input, _) = whitespace(input)?;
+        let (input, body) = cut(parse_block)(input)?;
+        if let Some(args) = template_args {
+            Ok((
+                input,
+                (
                     name.to_owned(),
-                    args.into_iter().map(|x| x.to_owned()).collect(),
-                    params,
-                    ret,
-                    body,
-                )),
-            ),
-        ))
+                    ConstExpr::PolyProc(PolyProcedure::new(
+                        name.to_owned(),
+                        args.into_iter().map(|x| x.to_owned()).collect(),
+                        params,
+                        ret,
+                        body,
+                    )),
+                ),
+            ))
+        } else {
+            Ok((
+                input,
+                (
+                    name.to_owned(),
+                    ConstExpr::Proc(Procedure::new(Some(name.to_owned()), params, ret, body)),
+                ),
+            ))
+        }
     } else {
-        Ok((
-            input,
-            (
-                name.to_owned(),
-                ConstExpr::Proc(Procedure::new(Some(name.to_owned()), params, ret, body)),
-            ),
-        ))
+        let (input, (params, ret)) = parse_fun_params(input)?;
+        trace!("Parsed method parameters: {params:#?}, {ret:#?}");
+        let (input, _) = whitespace(input)?;
+        let (input, body) = cut(parse_block)(input)?;
+        if let Some(args) = template_args {
+            Ok((
+                input,
+                (
+                    name.to_owned(),
+                    ConstExpr::PolyProc(PolyProcedure::new(
+                        name.to_owned(),
+                        args.into_iter().map(|x| x.to_owned()).collect(),
+                        params,
+                        ret,
+                        body,
+                    )),
+                ),
+            ))
+        } else {
+            Ok((
+                input,
+                (
+                    name.to_owned(),
+                    ConstExpr::Proc(Procedure::new(Some(name.to_owned()), params, ret, body)),
+                ),
+            ))
+        }
     }
 }
 
@@ -6481,10 +6427,7 @@
         branches.push((pat, body));
     }
 
-    // trace!("Parsed branches: {input}");
-    // trace!("Parsed branches: {branches:#?}");
-
-    let (input, _) = whitespace(input)?;
+    let (input, _) = whitespace(input)?;
     let (input, _) = tag("}")(input)?;
     Ok((input, Expr::Match(expr.into(), branches)))
 }
@@ -6549,8 +6492,7 @@
         context("tuple", parse_tuple_pattern),
         context("group", delimited(tag("("), cut(parse_pattern), tag(")"))),
         context("const", map(parse_const, Pattern::ConstExpr)),
-        // context("tuple", map(ma
-    ))(input)?;
+    ))(input)?;
     Ok((input, pattern))
 }
 
@@ -6759,8 +6701,8 @@
         // Optionally parse an alias
         let (input, alias) =
             opt(preceded(whitespace, preceded(tag("as"), cut(parse_symbol))))(input)?;
-        // let alias = alias.map(|x| x.to_owned());
-        // If there's a comma, continue parsing
+
+        // If there's a comma, continue parsing
         let (input, _) = whitespace(input)?;
 
         imports.push((path.to_owned(), alias));
@@ -6774,17 +6716,7 @@
             .map(|(x, y)| (x.to_owned(), y.map(|z| z.to_owned())))
             .collect();
 
-        // let mut decls = vec![];
-        // for (name, alias) in &imports {
-        //     // decls.push(Declaration::Const(alias.clone(), ConstExpr::var(module_name).field(ConstExpr::var(name))));
-        //     decls.push(Declaration::FromImport {
-        //         module: ,
-        //         name: name.clone(),
-        //         alias: alias.map(|x| x.to_owned()),
-        //     });
-        // }
-
-        let (input, _) = whitespace(input)?;
+        let (input, _) = whitespace(input)?;
         let (input, _) = tag(";")(input)?;
 
         return Ok((
@@ -6898,8 +6830,7 @@
 fn parse_if_expr<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
     input: &'a str,
 ) -> IResult<&'a str, Expr, E> {
-    // "if" <condition: Expr> <then: Block> <else: Option<Block>> => Expr::If(condition, Box::new(then), else.map(Box::new)),
-    let (input, _) = tag("if")(input)?;
+    let (input, _) = tag("if")(input)?;
     let (input, _) = whitespace(input)?;
     let (input, condition) = cut(parse_expr)(input)?;
     let (input, _) = whitespace(input)?;
@@ -6949,8 +6880,7 @@
 fn parse_if_let_expr<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
     input: &'a str,
 ) -> IResult<&'a str, Expr, E> {
-    // "if" <condition: Expr> <then: Block> <else: Option<Block>> => Expr::If(condition, Box::new(then), else.map(Box::new)),
-    let (input, _) = tag("if")(input)?;
+    let (input, _) = tag("if")(input)?;
     let (input, _) = whitespace(input)?;
     let (input, _) = tag("let")(input)?;
     let (input, _) = whitespace(input)?;
@@ -7005,8 +6935,7 @@
 fn parse_while_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
     input: &'a str,
 ) -> IResult<&'a str, Statement, E> {
-    // "while" <condition: Expr> <body: Block> => Statement::While(condition, Box::new(body)),
-    let (input, _) = tag("while")(input)?;
+    let (input, _) = tag("while")(input)?;
     let (input, _) = whitespace(input)?;
     let (input, condition) = cut(parse_expr)(input)?;
     let (input, _) = whitespace(input)?;
@@ -7020,8 +6949,7 @@
 fn parse_for_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
     input: &'a str,
 ) -> IResult<&'a str, Statement, E> {
-    // "for" <init: Option<Statement>> <condition: Option<Expr>> <step: Option<Statement>> <body: Block> => Statement::For(init.map(Box::new), condition.map(Box::new), step.map(Box::new), Box::new(body)),
-    let (input, _) = tag("for")(input)?;
+    let (input, _) = tag("for")(input)?;
     let (input, _) = whitespace(input)?;
     let (input, init) = cut(parse_short_stmt)(input)?;
     let (input, _) = whitespace(input)?;
@@ -7032,8 +6960,8 @@
     let (input, step) = cut(parse_short_stmt)(input)?;
     let (input, _) = whitespace(input)?;
     let (input, body) = cut(parse_block)(input)?;
-    // Ok((input, Statement::Expr(Expr::For(init.map(Box::new), condition.map(Box::new), step.map(Box::new), Box::new(body)))))
-    let mut init_expr = Expr::NONE;
+
+    let mut init_expr = Expr::NONE;
     let mut init_decl = Declaration::many(vec![]);
     match init {
         Statement::Declaration(decl, _) => init_decl = decl,
@@ -7060,11 +6988,7 @@
 fn parse_fun_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
     input: &'a str,
 ) -> IResult<&'a str, Statement, E> {
-    // "fun" <name: Symbol> <args: Tuple<(<(<Symbol> ":")?> <Type>)>> ":" <ret: Type> <body: Block> => {
-    //     let args: Vec<_> = args.into_iter().map(|(_name, ty)| ty).collect();
-    //     Statement::Declaration(Declaration::Proc(name.clone(), Procedure::new(name, args, ret, body)))
-    // },
-    let (input, _) = tag("fun")(input)?;
+    let (input, _) = tag("fun")(input)?;
     trace!("Parsing function");
     let (input, _) = whitespace(input)?;
     let (input, name) = cut(parse_symbol)(input)?;
@@ -7079,8 +7003,7 @@
     let (input, _) = whitespace(input)?;
     let (input, body) = parse_block(input)?;
     trace!("Parsed function body: {body}");
-    // Ok((input, Statement::Declaration(Declaration::Proc(name.to_owned(), Procedure::new(Some(name.to_owned()), params, ret, body)))))
-    if let Some(args) = template_args {
+    if let Some(args) = template_args {
         Ok((
             input,
             Statement::Declaration(
@@ -7114,11 +7037,7 @@
 fn parse_quick_fun_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
     input: &'a str,
 ) -> IResult<&'a str, Statement, E> {
-    // "fun" <name: Symbol> <args: Tuple<(<(<Symbol> ":")?> <Type>)>> ":" <ret: Type> <body: Block> => {
-    //     let args: Vec<_> = args.into_iter().map(|(_name, ty)| ty).collect();
-    //     Statement::Declaration(Declaration::Proc(name.clone(), Procedure::new(name, args, ret, body)))
-    // },
-    let (input, _) = tag("fun")(input)?;
+    let (input, _) = tag("fun")(input)?;
     trace!("Parsing function");
     let (input, _) = whitespace(input)?;
     let (input, name) = cut(parse_symbol)(input)?;
@@ -7137,8 +7056,8 @@
     let (input, _) = whitespace(input)?;
     let (input, _) = cut(tag(";"))(input)?;
     trace!("Parsed function body: {body}");
-    // Ok((input, Statement::Declaration(Declaration::Proc(name.to_owned(), Procedure::new(Some(name.to_owned()), params, ret, body)))))
-    if let Some(args) = template_args {
+
+    if let Some(args) = template_args {
         Ok((
             input,
             Statement::Declaration(
@@ -7190,8 +7109,7 @@
 
     let (input, _) = whitespace(input)?;
     let (input, last) = opt(pair(
-        // parse_symbol,
-        pair(
+        pair(
             map(opt(tag("mut")), |x| match x {
                 Some(_) => Mutability::Mutable,
                 None => Mutability::Immutable,
@@ -7540,7 +7458,7 @@
                 Declaration::Type(
                     name.to_owned(),
                     Type::Poly(
-                        params.into_iter().map(|x| x.to_owned()).collect(),
+                        params,
                         Type::Struct(fields).into(),
                     ),
                 ),
@@ -7601,7 +7519,7 @@
                 Declaration::Type(
                     name.to_owned(),
                     Type::Poly(
-                        params.into_iter().map(|x| x.to_owned()).collect(),
+                        params,
                         Type::EnumUnion(fields).into(),
                     ),
                 ),
@@ -7872,12 +7790,19 @@
 
 fn parse_type_params<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
     input: &'a str,
-) -> IResult<&'a str, Vec<String>, E> {
+) -> IResult<&'a str, Vec<(String, Option<Type>)>, E> {
     let (input, _) = tag("<")(input)?;
     let (input, _) = whitespace(input)?;
-    let (input, mut params) = many0(terminated(parse_symbol, tag(",")))(input)?;
+    let (input, mut params) = many0(terminated(alt((
+        preceded(delimited(whitespace, tag("const"), whitespace), map(pair(parse_symbol, delimited(terminated(whitespace, tag(":")), parse_type, whitespace)), |(name, ty)| (name, Some(ty)))),
+        map(parse_symbol, |x| (x, None))
+    )), preceded(whitespace, tag(","))))(input)?;
     let (input, _) = whitespace(input)?;
-    let (input, last_param) = opt(parse_symbol)(input)?;
+    let (input, last_param) = opt(alt((
+        preceded(delimited(whitespace, tag("const"), whitespace), map(pair(parse_symbol, delimited(terminated(whitespace, tag(":")), parse_type, whitespace)), |(name, ty)| (name, Some(ty)))),
+        // map(pair(parse_symbol, delimited(terminated(whitespace, tag(":")), parse_type, whitespace)), |(name, ty)| (name, Some(ty))),
+        map(parse_symbol, |x| (x, None))
+    )))(input)?;
     let (input, _) = whitespace(input)?;
     let (input, _) = tag(">")(input)?;
 
@@ -7885,7 +7810,7 @@
         params.push(last_param);
     }
 
-    Ok((input, params.into_iter().map(|x| x.to_string()).collect()))
+    Ok((input, params.into_iter().map(|(name, ty)| (name.to_string(), ty)).collect()))
 }
 
 fn parse_type_function<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
@@ -7928,19 +7853,23 @@
 ) -> IResult<&'a str, Type, E> {
     let (input, ty) = parse_type_atom(input)?;
     let (input, _) = whitespace(input)?;
-    let (input, _) = tag("<")(input)?;
-    let (input, _) = whitespace(input)?;
-    let (input, mut args) = many0(terminated(parse_type, tag(",")))(input)?;
-    let (input, _) = whitespace(input)?;
-    let (input, last_arg) = opt(parse_type)(input)?;
-    let (input, _) = whitespace(input)?;
-    let (input, _) = tag(">")(input)?;
 
-    if let Some(last_arg) = last_arg {
-        args.push(last_arg);
+    if let Ok((input, _)) = tag::<&str, &str, E>("<")(input) {
+        let (input, _) = whitespace(input)?;
+        let (input, mut args) = many0(terminated(parse_type, tag(",")))(input)?;
+        let (input, _) = whitespace(input)?;
+        let (input, last_arg) = opt(parse_type)(input)?;
+        let (input, _) = whitespace(input)?;
+        let (input, _) = tag(">")(input)?;
+    
+        if let Some(last_arg) = last_arg {
+            args.push(last_arg);
+        }
+    
+        Ok((input, Type::Apply(Box::new(ty), args)))
+    } else {
+        return Ok((input, ty))
     }
-
-    Ok((input, Type::Apply(Box::new(ty), args)))
 }
 
 fn parse_type_primitive<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
@@ -7976,6 +7905,7 @@
         parse_type_function,
         map(parse_symbol, |x| Type::Symbol(x.to_string())),
         parse_type_group,
+        map(parse_const_atom, |x| Type::ConstParam(x.into()))
     ))(input)?;
 
     Ok((input, ty))
@@ -8449,19 +8379,22 @@
 ) -> IResult<&'a str, ConstExpr, E> {
     let (input, expr) = parse_const_term(input)?;
     let (input, _) = whitespace(input)?;
-    let (input, _) = tag("<")(input)?;
-    let (input, _) = whitespace(input)?;
-    let (input, mut tys) = many0(terminated(parse_type, tag(",")))(input)?;
-    let (input, _) = whitespace(input)?;
-    let (input, last_ty) = opt(parse_type)(input)?;
-    let (input, _) = whitespace(input)?;
-    let (input, _) = tag(">")(input)?;
-
-    if let Some(last_ty) = last_ty {
-        tys.push(last_ty);
+    if let Ok((input, _)) = tag::<&str, &str, E>("<")(input) {
+        let (input, _) = whitespace(input)?;
+        let (input, mut tys) = many0(terminated(parse_type, tag(",")))(input)?;
+        let (input, _) = whitespace(input)?;
+        let (input, last_ty) = opt(parse_type)(input)?;
+        let (input, _) = whitespace(input)?;
+        let (input, _) = tag(">")(input)?;
+    
+        if let Some(last_ty) = last_ty {
+            tys.push(last_ty);
+        }
+    
+        Ok((input, expr.monomorphize(tys)))
+    } else {
+        Ok((input, expr))
     }
-
-    Ok((input, expr.monomorphize(tys)))
 }
 
 fn parse_const_variant<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
@@ -8528,6 +8461,7 @@
         parse_const_sizeof_expr,
         parse_const_sizeof_type,
         parse_const_tuple,
+        parse_const_group,
         parse_const_bool,
         parse_const_null,
         parse_const_none,
@@ -8545,7 +8479,6 @@
         }),
         parse_const_array,
         parse_const_struct,
-        parse_const_group,
         map(parse_symbol, |x| ConstExpr::Symbol(x.to_string())),
     ))(input)
 }
@@ -9018,7 +8951,7 @@
     fn compile_and_run(code: &str, input: &str) -> Result<String, String> {
         let _ = rayon::ThreadPoolBuilder::new()
             .num_threads(16)
-            .stack_size(2048 * 1024 * 1024)
+            .stack_size(512 * 1024 * 1024)
             .build_global();
         // Compiling most examples overflows the tiny stack for tests.
         // So, we spawn a new thread with a larger stack size.
@@ -9391,7 +9324,7 @@
         assert_parse_type(
             "fun<T>(Option<T>) -> Bool",
             Some(Type::Poly(
-                vec!["T".to_string()],
+                vec![("T".to_string(), None)],
                 Type::Proc(
                     vec![Type::Apply(
                         Box::new(Type::Symbol("Option".to_string())),
@@ -9406,7 +9339,7 @@
         assert_parse_type(
             "fun<T>(Option<T>, Int) -> Bool",
             Some(Type::Poly(
-                vec!["T".to_string()],
+                vec![("T".to_string(), None)],
                 Type::Proc(
                     vec![
                         Type::Apply(
@@ -9794,53 +9727,6 @@
         );
 
         trace!("Parsing block");
-        //         trace!("{:#?}", parse_suite::<nom::error::VerboseError<&str>>(0, r#"
-        // enum Result<T, E>:
-        //     Ok(T)
-        //     Err(E)
-
-        // struct Point:
-        //     x: Int
-        //     y: Int
-
-        // if True and 1 > 2 + 3:
-        //     println(a + b)
-        //     a - b
-        //     while not a:
-        //         println("Testing")
-        //         std.println<Int>(5)
-        //         increment(&mut a)
-
-        //         Result<Int, String> of Ok(5)
-
-        //         "#));
-
-        // impl Result<T, E>:
-        //     def unwrap(self) -> T:
-        //         match self:
-        //             of Ok(x) => x
-        //             of Err(e) => panic(e)
-    }
-
-    // #[test]
-    // fn test_parse_const_tuple() {
-    //     let input = "(a = 1, b = 2)";
-    //     let result = parse_const_tuple(input);
-    //     assert_eq!(result, Ok(("", ConstExpr::Tuple(vec![ConstExpr::Tuple(vec![ConstExpr::Symbol("a".to_string()), ConstExpr::Int(1)]), ConstExpr::Tuple(vec![ConstExpr::Symbol("b".to_string()), ConstExpr::Int(2)])]))));
-    // }
-
-    // #[test]
-    // fn test_parse_const_array() {
-    //     let input = "[1, 2, 3]";
-    //     let result = parse_const_array(input);
-    //     assert_eq!(result, Ok(("", ConstExpr::Array(vec![ConstExpr::Int(1), ConstExpr::Int(2), ConstExpr::Int(3)])));
-    // }
-
-    // #[test]
-    // fn test_parse_const_struct() {
-    //     let input = "struct {a = 1, b = 2}";
-    //     let result = parse_const_struct(input);
-    //     assert_eq!(result, Ok(("", ConstExpr::Struct(vec![("a".to_string(), ConstExpr::Int(1)), ("b".to_string(), ConstExpr::Int(2))].into_iter().collect())));
-    // }
-}
+    }
+}
 

\ No newline at end of file diff --git a/docs/src/sage/lir/compile.rs.html b/docs/src/sage/lir/compile.rs.html index 4eb108a6..4ac991da 100644 --- a/docs/src/sage/lir/compile.rs.html +++ b/docs/src/sage/lir/compile.rs.html @@ -1526,6 +1526,15 @@ 1525 1526 1527 +1528 +1529 +1530 +1531 +1532 +1533 +1534 +1535 +1536
//! # Compile
 //!
 //! This module contains the `Compile` trait, which allows an LIR expression to be compiled to one of the two variants of the assembly language.
@@ -2076,7 +2085,7 @@
             Self::EnumUnion(t, variant, val) => {
                 // Get the size of the tagged union.
                 let result_size = t.get_size(env)?;
-                let t = t.simplify_until_concrete(env)?;
+                let t = t.simplify_until_concrete(env, false)?;
                 if let Type::EnumUnion(fields) = t {
                     // Get the list of possible variant names.
                     let variants = fields.clone().into_keys().collect::<Vec<_>>();
@@ -2371,7 +2380,7 @@
                     // val_type.add_monomorphized_associated_consts(env)?;
 
                     // Push the address of the struct, tuple, or union onto the stack.
-                    match val_type.simplify_until_has_members(env)? {
+                    match val_type.simplify_until_has_members(env, false)? {
                         // If the value is a struct, tuple, or union:
                         Type::Struct(_) | Type::Tuple(_) | Type::Union(_) => {
                             // Compile a reference to the inner value with the expected mutability.
@@ -2456,7 +2465,7 @@
                     // val_type.add_monomorphized_associated_consts(env)?;
 
                     // Push the address of the struct, tuple, or union onto the stack.
-                    match val_type.simplify_until_has_members(env)? {
+                    match val_type.simplify_until_has_members(env, false)? {
                         // If the value is a struct, tuple, or union:
                         Type::Struct(_) | Type::Tuple(_) | Type::Union(_) => {
                             // Compile a reference to the inner value with the expected mutability.
@@ -2599,14 +2608,20 @@
         let ty = self.get_type(env)?;
         // Compile the constant expression.
         match self {
-            Self::Template(_, _) => {
+            Self::Any
+            | Self::Template(_, _) => {
                 // Cannot compile a template expression.
                 return Err(Error::UnsizedType(ty));
             }
 
-            Self::Type(_) => {
-                // Do nothing.
-            }
+            Self::Type(t) => {
+                if t.is_const_param() {
+                    let cexpr = t.simplify_until_const_param(env, false)?;
+                    cexpr.compile_expr(env, output)?
+                } else {
+                    return Err(Error::UnsizedType(ty));
+                }
+            }
             Self::Member(container, member) => {
                 let new_container = *container.clone();
                 debug!("Compiling (const) member access {member} on {new_container} in environment {env}");
@@ -2625,6 +2640,9 @@
                         }
                         fields[&name].clone().compile_expr(env, output)?
                     }
+                    (Self::Type(ty), member) if ty.is_const_param() => {
+                        ty.simplify_until_const_param(env, false)?.field(member).compile_expr(env, output)?
+                    }
                     (Self::Type(ty), Self::Symbol(name)) => {
                         if let Some((constant, _)) = env.get_associated_const(&ty, &name) {
                             debug!("Compiling associated constant {constant} in environment {env}");
@@ -2636,7 +2654,7 @@
                     }
                     (Self::Declare(bindings, expr), field) => {
                         let mut new_env = env.clone();
-                        new_env.add_declaration(&bindings)?;
+                        new_env.add_declaration(&bindings, true)?;
                         expr.field(field).compile_expr(&mut new_env, output)?;
                     }
                     (a, b) => {
@@ -2656,7 +2674,7 @@
             Self::Declare(bindings, body) => {
                 debug!("Compiling declaration {bindings} with body {body} in environment {env}");
                 let mut new_env = env.clone();
-                new_env.add_declaration(&bindings)?;
+                new_env.add_declaration(&bindings, true)?;
                 body.compile_expr(&mut new_env, output)?;
             }
             Self::Monomorphize(expr, ty_args) => match expr.eval(env)? {
@@ -2692,7 +2710,7 @@
                     }
 
                     let mut result = *result.clone();
-                    for (param, ty_arg) in params.into_iter().zip(ty_args) {
+                    for ((param, _), ty_arg) in params.into_iter().zip(ty_args) {
                         result.substitute(&param, &ty_arg);
                     }
                     result = result.eval(env)?;
@@ -2702,7 +2720,7 @@
                 }
                 Self::Declare(bindings, expr) => {
                     let mut new_env = env.clone();
-                    new_env.add_declaration(&bindings)?;
+                    new_env.add_declaration(&bindings, true)?;
                     expr.monomorphize(ty_args)
                         .compile_expr(&mut new_env, output)?;
                 }
@@ -2913,7 +2931,7 @@
             Self::EnumUnion(t, variant, val) => {
                 // Get the size of the tagged union.
                 let result_size = t.get_size(env)?;
-                let t = t.simplify_until_has_variants(env)?;
+                let t = t.simplify_until_has_variants(env, false)?;
 
                 // Get the inner list of variants and compile the expression using this information.
                 if let Type::EnumUnion(variants) = t.clone().simplify(env)? {
@@ -2987,7 +3005,7 @@
             Self::Of(enum_type, variant) => {
                 // Only try to simplify the type 50 times at most.
                 // This is to prevent infinite loops and to keep recursion under control.
-                match enum_type.simplify_until_has_variants(env)? {
+                match enum_type.simplify_until_has_variants(env, false)? {
                     // If the type is an enum, we can continue.
                     Type::Enum(variants) => {
                         // Get the index of the variant.
diff --git a/docs/src/sage/lir/env.rs.html b/docs/src/sage/lir/env.rs.html
index da0cb73e..ac602c8b 100644
--- a/docs/src/sage/lir/env.rs.html
+++ b/docs/src/sage/lir/env.rs.html
@@ -1298,17 +1298,6 @@
 1297
 1298
 1299
-1300
-1301
-1302
-1303
-1304
-1305
-1306
-1307
-1308
-1309
-1310
 
//! # Environment
 //!
 //! This module defines the `Env` type, which is used to store the types, constants, and procedures
@@ -1564,10 +1553,13 @@
         for (other_ty, consts) in associated_constants.iter() {
             if matches!(ty.is_monomorph_of(other_ty, self), Ok(true)) {
                 debug!("Type {ty} is monomorph of {other_ty}");
+                for (name, (constant, ty)) in consts {
+                    debug!("   {name}: {ty} = {constant}")
+                }
                 let template = other_ty.clone();
 
                 let ty_params = template.get_template_params(self);
-                let ty_param_set = ty_params.clone().into_iter().collect::<HashSet<_>>();
+                let ty_param_set = ty_params.clone().into_iter().map(|x| x.0).collect::<HashSet<_>>();
                 let monomorph = ty.clone();
                 debug!("Monomorph of {template} is {monomorph}");
                 let mut symbols = HashMap::new();
@@ -1583,12 +1575,12 @@
                     debug!("Failed to get monomorph template args for {monomorph} of {template}");
                     continue;
                 }
-                for (symbol, ty) in &symbols {
-                    debug!("----> {symbol} == {ty}");
+                for (symbol, (ty, specifier)) in &symbols {
+                    debug!("----> {symbol} == {ty}: {specifier:?}");
                 }
                 let template_associated_consts = consts.clone();
                 let mut ty_args = Vec::new();
-                for ty_param in &ty_params {
+                for (ty_param, _) in &ty_params {
                     if let Some(arg) = symbols.get(ty_param) {
                         ty_args.push(arg.clone());
                     } else {
@@ -1597,8 +1589,8 @@
                 }
 
                 if ty_args.len() != ty_params.len() {
-                    debug!("Mismatched number of template arguments for {monomorph} of {template}");
-                    debug!("Expected {ty_params:?}, found {ty_args:?}");
+                    error!("Mismatched number of template arguments for {monomorph} of {template}");
+                    error!("Expected {ty_params:?}, found {ty_args:?}");
                     continue;
                 }
 
@@ -1609,10 +1601,9 @@
 
                 if let Some((_, const_ty)) = template_associated_consts.get(name) {
                     debug!("Found cached associated const (type) {name} of type {const_ty}");
-                    // let result = const_ty.apply(ty_args.clone()).simplify_until_simple(self).ok()?;
-                    // let result = const_ty.apply(ty_args.clone());
-                    let result = const_ty.apply(ty_args.clone());
-                    match result.simplify_until_simple(self) {
+
+                    let result = const_ty.apply(ty_args.clone().into_iter().map(|x|x.0).collect());
+                    match result.simplify_until_simple(self, false) {
                         Ok(result) => {
                             debug!("Found associated const (type) {name} of type {ty} = {result}");
                             return Some(result);
@@ -1620,24 +1611,23 @@
                         Err(_err) => {
                             debug!("Found associated const (type) {name} of type {ty} = {result} (failed to simplify)");
                             return Some(result);
-                            // debug!("Failed to simplify associated const (type) {name} of type {ty} = {result}");
-                            // debug!("Error: {err}");
-                            // continue;
-                        }
+                        }
                     }
-                    // info!("Found associated const (type) {name} of type {ty} = {result}");
-                    // return Some(result);
-                }
+                }
 
                 debug!("Could not find associated const {name} of type {ty} in {template}");
                 for template_const_name in template_associated_consts.keys() {
                     debug!("   {template_const_name} != {name}");
                 }
+            } else {
+                debug!("Type {ty} is not monomorph of {other_ty}");
             }
 
             if !ty.can_decay_to(other_ty, self).unwrap_or(false) {
-                trace!("Type {other_ty} does not equal {ty}");
+                debug!("Type {other_ty} does not equal {ty}");
                 continue;
+            } else {
+                debug!("Type {other_ty} equals {ty}");
             }
             if let Some((constant, expr_ty)) = consts.get(name) {
                 let constant = constant.clone();
@@ -1648,7 +1638,6 @@
                 return Some(expr_ty);
             }
         }
-        trace!("Could not find associated const {name} of type {ty} in {self}");
         drop(associated_constants);
 
         if let Type::Type(inner_ty) = ty {
@@ -1666,11 +1655,12 @@
                 return Some(ty);
             }
         }
+        error!("Could not find associated const {name} of type {ty} in {self}");
         None
     }
 
     pub fn get_associated_const(&self, ty: &Type, name: &str) -> Option<(ConstExpr, Type)> {
-        trace!(
+        debug!(
             "Getting associated const {name} of type {ty} in {self} with types {:?}",
             self.types
         );
@@ -1692,7 +1682,7 @@
                 let monomorph = ty.clone();
                 let mut symbols = HashMap::new();
                 let ty_params = template.get_template_params(self);
-                let ty_param_set = ty_params.clone().into_iter().collect::<HashSet<_>>();
+                let ty_param_set = ty_params.clone().into_iter().map(|x| x.0).collect::<HashSet<_>>();
                 if monomorph
                     .get_monomorph_template_args(
                         &template.strip_template(self),
@@ -1705,16 +1695,16 @@
                     debug!("Failed to get monomorph template args for {monomorph} of {template}");
                     continue;
                 }
-                for (symbol, ty) in &symbols {
-                    debug!("----> {symbol} == {ty}");
+                for (symbol, (ty, expected)) in &symbols {
+                    debug!("----> {symbol} == {ty}, {expected:?}");
                 }
                 let template_associated_consts = consts.clone();
                 let mut ty_args = Vec::new();
-                for ty_param in &ty_params {
-                    if let Some(arg) = symbols.get(ty_param) {
+                for (ty_param, _) in &ty_params {
+                    if let Some((arg, _)) = symbols.get(ty_param) {
                         ty_args.push(arg.clone());
                     } else {
-                        continue;
+                        debug!("Could not find symbol {ty_param}");
                     }
                 }
 
@@ -1727,7 +1717,7 @@
                 if let Some((const_expr, const_ty)) = template_associated_consts.get(name) {
                     debug!("Found cached associated const pair: {const_expr} with type {const_ty}");
                     let mut result_ty = const_ty.apply(ty_args.clone());
-                    result_ty = match result_ty.simplify_until_simple(self) {
+                    result_ty = match result_ty.simplify_until_simple(self, true) {
                         Ok(result) => {
                             debug!("Found associated const {name} of type {ty} = {result}");
                             result
@@ -1747,8 +1737,8 @@
                 debug!("Could not find associated const {name} of type {ty} in {template}");
                 // return self.get_associated_const(&monomorph, name);
             } else {
-                // info!("Type {ty} is not monomorph of {other_ty}");
-            }
+                debug!("Type {ty} is not monomorph of {other_ty}");
+            }
 
             if !ty.can_decay_to(other_ty, self).unwrap_or(false) {
                 trace!("Type {other_ty} does not equal {ty}");
@@ -1884,7 +1874,7 @@
     ) -> Result<(), Error> {
         debug!("Adding monomorphized associated constants of type {template} to {monomorph} with type arguments {ty_args:?} to environment");
 
-        let monomorph = if let Ok(simplified) = monomorph.simplify_until_simple(self) {
+        let monomorph = if let Ok(simplified) = monomorph.simplify_until_simple(self, false) {
             debug!("Simplified {monomorph} to {simplified}");
             simplified
         } else {
@@ -1951,7 +1941,7 @@
             // Strip off the template parameters from the type arguments.
             let mono_const = if let ConstExpr::Template(ty_params, cexpr) = const_expr {
                 let mut tmp = *cexpr.clone();
-                for (param, arg) in ty_params.iter().zip(ty_args.iter()) {
+                for ((param, _), arg) in ty_params.iter().zip(ty_args.iter()) {
                     tmp.substitute(param, arg);
                 }
                 tmp
@@ -1976,7 +1966,7 @@
         expr: ConstExpr,
     ) -> Result<(), Error> {
         let associated_const_name = associated_const_name.to_string();
-        trace!("Defining associated const {associated_const_name} as {expr} to type {ty}");
+        debug!("Defining associated const {associated_const_name} as {expr} to type {ty}");
         let expr_ty = expr.get_type(self)?;
         let mut associated_constants = self.associated_constants.write().unwrap();
         associated_constants
@@ -1988,9 +1978,9 @@
     }
 
     /// Add all the declarations to this environment.
-    pub(super) fn add_declaration(&mut self, declaration: &Declaration) -> Result<(), Error> {
+    pub(super) fn add_declaration(&mut self, declaration: &Declaration, compiling: bool) -> Result<(), Error> {
         self.add_compile_time_declaration(declaration)?;
-        self.add_local_variable_declaration(declaration)?;
+        self.add_local_variable_declaration(declaration, compiling)?;
         Ok(())
     }
 
@@ -2082,10 +2072,10 @@
                     let name = alias.clone().unwrap_or(name.clone());
 
                     // if !self.types.contains_key(&name) {
-                    self.define_const(&name, access.clone());
-                    if let Ok(Type::Type(ty)) = access.get_type(self) {
-                        self.define_type(name, *ty);
+                    if let Ok(Type::Type(ty)) = access.get_type(self) {
+                        self.define_type(&name, *ty);
                     }
+                    self.define_const(&name, access.clone());
                 }
             }
             Declaration::FromImportAll(module) => {
@@ -2095,10 +2085,10 @@
                     for name in fields.keys() {
                         let access = module.clone().field(ConstExpr::Symbol(name.clone()));
 
-                        self.define_const(name, access.clone());
                         if let Ok(Type::Type(ty)) = access.get_type(self) {
                             self.define_type(name, *ty);
                         }
+                        self.define_const(name, access.clone());
                     }
                 } else {
                     error!("Invalid module type: {module_ty}");
@@ -2163,12 +2153,11 @@
 
                     for (name, associated_const) in impls {
                         let templated_const =
-                            associated_const.template(supplied_param_symbols.clone());
+                            associated_const.template(template_params.clone().into_iter().zip(supplied_param_symbols.clone().into_iter()).map(|((_, ty), param)| (param, ty)).collect());
                         self.add_associated_const(*template.clone(), name, templated_const)?;
                     }
                 } else {
-                    // ty.add_monomorphized_associated_consts(self)?;
-                    for (name, associated_const) in impls {
+                    for (name, associated_const) in impls {
                         self.add_associated_const(ty.clone(), name, associated_const.clone())?;
                     }
 
@@ -2177,24 +2166,8 @@
                     // })?;
                 }
             }
-            Declaration::Var(_, _, Some(_ty), _e) => {
-                // ty.add_monomorphized_associated_consts(self).ok();
-                // if let Ok(ty) = e.get_type(self) {
-                //     ty.add_monomorphized_associated_consts(self).ok();
-                // }
-            }
-            Declaration::Var(_, _, _, _e) => {
-                // Variables are not defined at compile-time.
-                // if let Ok(ty) = e.get_type(self) {
-                //     ty.add_monomorphized_associated_consts(self).ok();
-                // }
-            }
-            Declaration::VarPat(_, _e) => {
-                // Variables are not defined at compile-time.
-                // if let Ok(ty) = e.get_type(self) {
-                //     ty.add_monomorphized_associated_consts(self).ok();
-                // }
-            }
+            Declaration::Var(_, _, _, _) => {}
+            Declaration::VarPat(_, _) => {}
             Declaration::Many(decls) => {
                 for decl in decls.iter() {
                     self.add_compile_time_declaration(decl)?;
@@ -2220,6 +2193,7 @@
     pub(super) fn add_local_variable_declaration(
         &mut self,
         declaration: &Declaration,
+        compiling: bool
     ) -> Result<(), Error> {
         trace!("Adding local declaration {declaration}");
         match declaration {
@@ -2259,7 +2233,7 @@
                     None => expr.get_type(self)?,
                 };
                 // ty.add_monomorphized_associated_consts(self)?;
-                self.define_var(name, *mutability, ty)?;
+                self.define_var(name, *mutability, ty, compiling)?;
             }
             Declaration::VarPat(pat, expr) => {
                 let ty = expr.get_type(self)?;
@@ -2268,7 +2242,7 @@
             }
             Declaration::Many(decls) => {
                 for decl in decls.iter() {
-                    self.add_local_variable_declaration(decl)?;
+                    self.add_local_variable_declaration(decl, compiling)?;
                 }
             }
         }
@@ -2305,19 +2279,28 @@
     /// Define a type with a given name under this environment.
     pub(super) fn define_type(&mut self, name: impl ToString, ty: Type) {
         let name = name.to_string();
-
+        trace!("Defining type {name} as {ty}");
+        if ty.is_const_param() {
+            if let Ok(ty) = ty.clone().simplify_until_const_param(self, false) {
+                self.define_const(&name, ty);
+                return;
+            }
+        }
         match &ty {
             Type::Symbol(sym) if sym == &name => {
                 trace!("Defining type {ty} to itself as {name}");
             }
             _ => {
-                trace!("Defining type {name} as {ty}");
                 Arc::make_mut(&mut self.consts).insert(name.clone(), ConstExpr::Type(ty.clone()));
-                Arc::make_mut(&mut self.types).insert(name, ty.clone());
+                Arc::make_mut(&mut self.types).insert(name.clone(), ty.clone());
 
-                if let Ok(simplified) = ty.simplify_until_concrete(self) {
+                if let Ok(simplified) = ty.simplify_until_concrete(self, false) {
                     if let Ok(size) = simplified.get_size(self) {
-                        self.set_precalculated_size(simplified, size);
+                        self.set_precalculated_size(simplified.clone(), size);
+                    }
+                    if let Type::ConstParam(cexpr) = simplified {
+                        trace!("Found const param \"{name}\": {cexpr}");
+                        self.define_const(&name, *cexpr);
                     }
                 }
             }
@@ -2332,34 +2315,8 @@
     /// typechecking errors if the environment does not already have a memoized size
     /// for the type of a subexpression.
     pub fn define_types(&mut self, types: Vec<(String, Type)>) {
-        for (name, ty) in &types {
-            match &ty {
-                Type::Symbol(sym) if sym == name => {
-                    trace!("Defining type {ty} to itself as {name}");
-                }
-                _ => {
-                    if self.types.contains_key(name) {
-                        debug!("Redefining type {name} in {self}");
-                    } else {
-                        trace!("Defining type {name} as {ty}");
-                        Arc::make_mut(&mut self.consts)
-                            .insert(name.clone(), ConstExpr::Type(ty.clone()));
-                        Arc::make_mut(&mut self.types).insert(name.clone(), ty.clone());
-                    }
-                }
-            }
-        }
-
-        for (_, ty) in types {
-            if let Ok(simplified) = ty.simplify_until_concrete(self) {
-                if let Ok(size) = simplified.get_size(self) {
-                    self.set_precalculated_size(simplified, size);
-                } else {
-                    debug!("Failed to memoize type size for {simplified}");
-                }
-            } else {
-                debug!("Failed to simplify type {ty}");
-            }
+        for (name, ty) in types {
+            self.define_type(name, ty)
         }
     }
 
@@ -2371,6 +2328,7 @@
     /// Define a constant with a given name under this environment.
     pub(super) fn define_const(&mut self, name: impl ToString, e: ConstExpr) {
         let name = name.to_string();
+        trace!("Defining constant {name} as {e}");
 
         /*
         Removed this code in favor of using Declaration::FromImport
@@ -2480,6 +2438,7 @@
     pub(super) fn define_args(
         &mut self,
         args: Vec<(String, Mutability, Type)>,
+        compiling: bool,
     ) -> Result<usize, Error> {
         debug!("Defining arguments {args:?} in\n{self}");
         self.fp_offset = 1;
@@ -2488,7 +2447,12 @@
         // For each argument in reverse order (starting from the last argument)
         for (name, mutability, ty) in args.into_iter().rev() {
             // Get the size of the argument we're defining.
-            let size = ty.get_size(self)?;
+            let size = if compiling {
+                ty.get_size(self)?
+            } else {
+                0
+            };
+            
             // Add the size of the argument to the total number of cells taken up by the arguments.
             self.args_size += size;
             // Decrement the frame pointer offset by the size of the argument
@@ -2517,16 +2481,28 @@
         var: impl ToString,
         mutability: Mutability,
         ty: Type,
+        compiling: bool
     ) -> Result<isize, Error> {
         let var = var.to_string();
         // Get the size of the variable we're defining.
-        let size = ty.get_size(self)? as isize;
+        let size = if compiling {
+            ty.get_size(self)?
+        } else {
+            0
+        } as isize;
         // Remember the offset of the variable under the current scope.
         let offset = self.fp_offset;
         // Increment the frame pointer offset by the size of the variable
         // so that the next variable is allocated directly after this variable.
         debug!("Defining variable {var} of type {ty} at {offset} in\n{self}");
         self.fp_offset += size;
+
+        let ty = match ty {
+            Type::Type(ty) => *ty,
+            Type::ConstParam(ty) => ty.get_type(self)?,
+            other => other
+        };
+        
         // Store the variable's type and offset in the environment.
         Arc::make_mut(&mut self.vars).insert(var, (mutability, ty, offset));
         // Return the offset of the variable from the frame pointer.
@@ -2586,37 +2562,39 @@
 
 impl Display for Env {
     fn fmt(&self, f: &mut Formatter) -> FmtResult {
+        writeln!(f, "Env")?;
         // return Ok(());
-        writeln!(f, "Env")?;
-        writeln!(f, "   Types:")?;
-        for (name, ty) in self.types.iter() {
-            writeln!(f, "      {}: {}", name, ty)?;
-            let constants = self.get_all_associated_consts(ty);
-            if constants.is_empty() {
-                continue;
+        /*
+        writeln!(f, "   Types:")?;
+        for (name, ty) in self.types.iter() {
+            writeln!(f, "      {}: {}", name, ty)?;
+            let constants = self.get_all_associated_consts(ty);
+            if constants.is_empty() {
+                continue;
+            }
+            writeln!(f, "         Associated constants:")?;
+            for (name, cexpr) in constants {
+                writeln!(f, "            {}: {}", name, cexpr)?;
             }
-            // writeln!(f, "         Associated constants:")?;
-            // for (name, cexpr) in constants {
-            //     writeln!(f, "            {}: {}", name, cexpr)?;
-            // }
-        }
-        // writeln!(f, "   Constants:")?;
-        // for (i, (name, e)) in self.consts.iter().enumerate() {
-        //     writeln!(f, "      {i}. {}: {}", name, e)?;
-        // }
-        // writeln!(f, "   Procedures:")?;
-        // for (name, proc) in self.procs.iter() {
-        //     writeln!(f, "      {}: {}", name, proc)?;
-        // }
-        writeln!(f, "   Globals:")?;
-        for (name, (mutability, ty, location)) in self.static_vars.iter() {
-            writeln!(f, "      {mutability} {name}: {ty} (location {location})")?;
         }
-        writeln!(f, "   Variables:")?;
-        for (name, (mutability, ty, offset)) in self.vars.iter() {
-            writeln!(f, "      {mutability} {name}: {ty} (frame-offset {offset})")?;
+        writeln!(f, "   Constants:")?;
+        for (i, (name, e)) in self.consts.iter().enumerate() {
+            writeln!(f, "      {i}. {}: {}", name, e)?;
         }
-        Ok(())
+        writeln!(f, "   Procedures:")?;
+        for (name, proc) in self.procs.iter() {
+            writeln!(f, "      {}: {}", name, proc)?;
+        }
+        writeln!(f, "   Globals:")?;
+        for (name, (mutability, ty, location)) in self.static_vars.iter() {
+            writeln!(f, "      {mutability} {name}: {ty} (location {location})")?;
+        }
+        writeln!(f, "   Variables:")?;
+        for (name, (mutability, ty, offset)) in self.vars.iter() {
+            writeln!(f, "      {mutability} {name}: {ty} (frame-offset {offset})")?;
+        }
+         */
+        Ok(())
     }
 }
 
\ No newline at end of file diff --git a/docs/src/sage/lir/error.rs.html b/docs/src/sage/lir/error.rs.html index 15ea0bad..3a73f628 100644 --- a/docs/src/sage/lir/error.rs.html +++ b/docs/src/sage/lir/error.rs.html @@ -345,6 +345,13 @@ 344 345 346 +347 +348 +349 +350 +351 +352 +353
use super::{
     Annotation, AssignOp, BinaryOp, ConstExpr, Expr, Mutability, Pattern, PolyProcedure, TernaryOp,
     Type, UnaryOp,
@@ -364,7 +371,11 @@
     ),
 
     UnimplementedOperator(String),
-
+    /// An error caused by unexpectedly passing a constant parameter to a template.
+    UnexpectedConstParam {
+        found: Type,
+        expr: Expr
+    },
     /// An error caused by trying to assemble invalid code generated by the compiler.
     /// This should be taken seriously, unless the error is due to an invalid handwritten builtin.
     AssemblyError(crate::asm::Error),
@@ -505,6 +516,9 @@
 impl Display for Error {
     fn fmt(&self, f: &mut Formatter) -> FmtResult {
         match self {
+            Self::UnexpectedConstParam { found, expr } => {
+                write!(f, "unexpected constant parameter {found} in expression {expr}")
+            }
             Self::Annotated(err, _) => {
                 write!(f, "{err}")
             }
diff --git a/docs/src/sage/lir/expr/const_expr.rs.html b/docs/src/sage/lir/expr/const_expr.rs.html
index 95fb0085..2f9c453f 100644
--- a/docs/src/sage/lir/expr/const_expr.rs.html
+++ b/docs/src/sage/lir/expr/const_expr.rs.html
@@ -1150,6 +1150,125 @@
 1149
 1150
 1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
 
//! # Constant Expressions
 //!
 //! Constant expressions are expressions that can be evaluated at compile time.
@@ -1181,6 +1300,8 @@
     /// Bind a list of types in a constant expression.
     Declare(Box<Declaration>, Box<Self>),
 
+    /// The expression equal to any other expression.
+    Any,
     /// The unit, or "void" instance.
     None,
     /// The null pointer constant.
@@ -1238,7 +1359,7 @@
     /// Monomorphize a constant expression with some type arguments.
     Monomorphize(Box<Self>, Vec<Type>),
 
-    Template(Vec<String>, Box<Self>),
+    Template(Vec<(String, Option<Type>)>, Box<Self>),
 
     /// Get an attribute of a constant expression.
     Member(Box<Self>, Box<Self>),
@@ -1255,7 +1376,23 @@
         Self::Monomorphize(Box::new(self), ty_args)
     }
 
-    pub fn template(&self, params: Vec<String>) -> Self {
+    pub fn equals(&self, other: &Self, env: &Env) -> bool {
+        debug!("{self} == {other} in const?");
+        match (self, other) {
+            (Self::Any, _) | (_, Self::Any) => true,
+            (Self::Type(Type::Any), _) | (_, Self::Type(Type::Any)) => true,
+            (Self::Symbol(name), other) | (other, Self::Symbol(name)) => {
+                if let Some(c) = env.get_const(name) {
+                    c.equals(other, env)
+                } else {
+                    &Self::Symbol(name.clone()) == other
+                }
+            }
+            (a, b) => a == b,
+        }
+    }
+
+    pub fn template(&self, params: Vec<(String, Option<Type>)>) -> Self {
         match self {
             Self::Proc(proc) => Self::PolyProc(PolyProcedure::from_mono(proc.clone(), params)),
             Self::Declare(decls, inner) => inner.template(params).with(decls.clone()),
@@ -1381,7 +1518,7 @@
 
                 Self::Member(container, member) => {
                     let container_ty = container.get_type_checked(env, i)?;
-                    trace!("Member access on type: {container_ty}: {container} . {member}");
+                    debug!("Member access on type: {container_ty:?}: {container} . {member}");
                     Ok(match (*container.clone(), *member.clone()) {
                         (Self::Annotated(inner, metadata), member) => {
                             Self::Member(inner, member.into())
@@ -1448,7 +1585,23 @@
                             trace!("Found struct field: {container_ty} . {member}");
                             fields[&name].clone().eval_checked(env, i)?
                         }
+                        (Self::Type(ty), Self::Int(n)) => {
+                            warn!("Getting member {n} from {ty}");
+                            if ty.is_const_param() {
+                                let cexpr = ty.simplify_until_const_param(env, false)?;
+                                return cexpr.field(Self::Int(n)).eval_checked(env, i)
+                            } else {
+                                // return Err(Error::MemberNotFound((*container).into(), *member));
+                                return Ok(Self::Type(ty).field(Self::Int(n)));
+                            }
+                        }
                         (Self::Type(ty), Self::Symbol(name)) => {
+                            debug!("Getting member {name} from {ty}");
+                            if ty.is_const_param() {
+                                let cexpr = ty.simplify_until_const_param(env, false)?;
+                                return cexpr.eval_checked(env, i)?.field(Self::Symbol(name)).eval_checked(env, i)
+                            }
+
                             if let Some((constant, _)) = env.get_associated_const(&ty, &name) {
                                 constant.eval_checked(env, i)?
                             } else {
@@ -1462,7 +1615,7 @@
                                 error!(
                                     "Type member access not implemented for: {container_ty} . {member}, symbol {name} not defined"
                                 );
-                                return Err(Error::SymbolNotDefined(name));
+                                return Ok(Self::Type(ty).field(Self::Symbol(name)));
                             }
                         }
 
@@ -1492,7 +1645,9 @@
                         }
                     })
                 }
-                Self::None
+                
+                Self::Any
+                | Self::None
                 | Self::Null
                 | Self::Cell(_)
                 | Self::Int(_)
@@ -1504,8 +1659,15 @@
                 | Self::StandardBuiltin(_)
                 | Self::FFIProcedure(_)
                 | Self::Proc(_)
-                | Self::PolyProc(_)
-                | Self::Type(_) => Ok(self),
+                | Self::PolyProc(_) => Ok(self),
+                Self::Type(ty) => {
+                    if ty.is_const_param() {
+                        let cexpr = ty.simplify_until_const_param(env, false)?;
+                        cexpr.eval_checked(env, i)
+                    } else {
+                        Ok(Self::Type(ty.clone()))
+                    }
+                }
 
                 Self::Declare(bindings, expr) => {
                     debug!("Declaring compile time bindings: {bindings}");
@@ -1514,34 +1676,42 @@
                     Ok(expr.eval_checked(&new_env, i)?.with(bindings))
                 }
 
-                Self::Monomorphize(expr, ty_args) => Ok(match expr.clone().eval(env)? {
-                    Self::Template(params, ret) => {
-                        if params.len() != ty_args.len() {
-                            return Err(Error::InvalidMonomorphize(*expr));
+                Self::Monomorphize(expr, ty_args) => {
+                    // let ty_args = ty_args.into_iter().map(|t| t.simplify(env)).collect::<Result<Vec<_>, _>>()?;
+                    debug!("Monomorphizing {expr} with ty_args {ty_args:?}");
+
+                    Ok(match expr.clone().eval(env)? {
+                        Self::Template(params, ret) => {
+                            if params.len() != ty_args.len() {
+                                return Err(Error::InvalidMonomorphize(*expr));
+                            }
+                            let mut ret = ret.clone();
+
+                            for ((param, _), ty_arg) in params.iter().zip(ty_args.iter()) {
+                                ret.substitute(param, ty_arg);
+                            }
+                            *ret
                         }
-                        let mut ret = ret.clone();
+                        Self::PolyProc(proc) => {
+                            Self::Proc(proc.monomorphize(ty_args.clone(), env)?)
+                        },
+                        Self::Declare(bindings, expr) => {
+                            let mut new_env = env.clone();
+                            new_env.add_compile_time_declaration(&bindings)?;
+                            expr.monomorphize(ty_args.clone())
+                                .eval_checked(&new_env, i)?
+                                .with(bindings)
+                        }
+                        Self::Annotated(_inner, metadata) => expr
+                            .monomorphize(ty_args.clone())
+                            .eval_checked(env, i)
+                            .map_err(|x| x.annotate(metadata))?,
 
-                        for (param, ty_arg) in params.iter().zip(ty_args.iter()) {
-                            ret.substitute(param, ty_arg);
+                        _other => {
+                            Self::Monomorphize(Box::new(expr.eval_checked(env, i)?), ty_args.clone())
                         }
-                        *ret
-                    }
-                    Self::PolyProc(proc) => Self::Proc(proc.monomorphize(ty_args.clone(), env)?),
-                    Self::Declare(bindings, expr) => {
-                        let mut new_env = env.clone();
-                        new_env.add_compile_time_declaration(&bindings)?;
-                        expr.monomorphize(ty_args.clone())
-                            .eval_checked(&new_env, i)?
-                            .with(bindings)
-                    }
-                    Self::Annotated(_inner, metadata) => expr
-                        .monomorphize(ty_args.clone())
-                        .eval_checked(env, i)
-                        .map_err(|x| x.annotate(metadata))?,
-                    _other => {
-                        Self::Monomorphize(Box::new(expr.eval_checked(env, i)?), ty_args.clone())
-                    }
-                }),
+                    })
+                },
 
                 Self::TypeOf(expr) => Ok(Self::Array(
                     expr.get_type_checked(env, i)?
@@ -1666,7 +1836,10 @@
             // If not, evaluate it and see if it's a symbol.
             other => match other.eval(env)? {
                 Self::Symbol(name) => Ok(name),
-                other => Err(Error::NonSymbol(other)),
+                other => {
+                    // error!("Could not convert {other} to symbol");
+                    Err(Error::NonSymbol(other))
+                },
             },
         }
     }
@@ -1682,15 +1855,28 @@
     fn get_type_checked(&self, env: &Env, i: usize) -> Result<Type, Error> {
         trace!("Getting type from constexpr: {self}");
         Ok(match self.clone() {
+            Self::Any => Type::Any,
             Self::Template(params, expr) => {
                 let mut new_env = env.clone();
-                for param in &params {
-                    new_env.define_type(param, Type::Symbol(param.clone()));
+                for (param, ty) in &params {
+                    if let Some(ty) = ty {
+                        new_env.define_type(param, ty.clone());
+                    } else {
+                        new_env.define_type(param, Type::Symbol(param.clone()));
+                    }
                 }
                 Type::Poly(params, expr.get_type_checked(&new_env, i)?.into())
             }
 
-            Self::Type(t) => Type::Type(t.into()),
+            Self::Type(t) => {
+                debug!("Getting type of type {t}");
+                if t.is_const_param() {
+                    let cexpr = t.simplify_until_const_param(env, false)?;
+                    cexpr.get_type(env)?
+                } else {
+                    Type::Type(t.into())
+                }
+            }
 
             Self::Member(val, field) => {
                 // Get the field to access (as a symbol)
@@ -1700,10 +1886,11 @@
                 let as_int = field.clone().as_int(env);
 
                 let val_type = val.get_type_checked(env, i)?;
-                debug!("Got type of container access {val} . {field}\nContainer: {val_type}");
-                // val_type.add_monomorphized_associated_consts(env)?;
-                // Get the type of the value to get the member of.
-                match &val_type.simplify_until_concrete(env)? {
+                debug!("Got type of container access {val} . {field}\nContainer: {val_type:?}, is_const_param: {}", val_type.is_const_param());
+
+                // Get the type of the value to get the member of.
+                let val_type = val_type.simplify_until_concrete(env, false)?;
+                match &val_type {
                     Type::Unit(_unit_name, inner_ty) => {
                         // Get the type of the field.
                         env.get_type_of_associated_const(inner_ty, &as_symbol?)
@@ -1712,7 +1899,7 @@
 
                     Type::Pointer(_found_mutability, t) => {
                         let val = &Expr::ConstExpr(*val);
-                        let t = t.clone().simplify_until_concrete(env)?;
+                        let t = t.clone().simplify_until_concrete(env, false)?;
                         match t.get_member_offset(&field, val, env) {
                             Ok((t, _)) => t,
                             Err(_) => {
@@ -1727,10 +1914,18 @@
                     }
 
                     Type::Type(ty) => {
-                        // Get the associated constant expression's type.
-                        env.get_type_of_associated_const(ty, &as_symbol?)
-                            .ok_or(Error::MemberNotFound((*val.clone()).into(), *field.clone()))?
-                    }
+                        debug!("Got type {ty}");
+                        if ty.is_const_param() {
+                            ty.simplify_until_const_param(env, false)?.eval(env)?.field(*field).get_type_checked(env, i)?
+                        } else {
+                            // Get the associated constant expression's type.
+                            if let Ok((ty, _)) = ty.get_member_offset(&field, &Expr::from(self.clone()), env) {
+                                return Ok(ty);
+                            }
+                            env.get_type_of_associated_const(ty, &as_symbol?)
+                                .ok_or(Error::MemberNotFound((*val.clone()).into(), *field.clone()))?
+                        }
+                    }
                     // If we're accessing a member of a tuple,
                     // we use the `as_int` interpretation of the field.
                     // This is because tuples are accesed by integer index.
@@ -1792,7 +1987,6 @@
                             t.clone()
                         } else {
                             // If the field is not in the union, return an error.
-                            // return Err(Error::MemberNotFound((*val.clone()).into(), (*field.clone()).into()));
                             return ConstExpr::Member(
                                 ConstExpr::Type(val_type).into(),
                                 field.clone(),
@@ -1859,21 +2053,39 @@
                             .simplify_until_type_checks(env);
                     }
                     Self::Template(params, ret) => {
+                        debug!("Getting type of monomorphized template {self}");
                         if params.len() != ty_args.len() {
                             return Err(Error::InvalidMonomorphize(expr));
                         }
 
                         let mut ret = ret.clone();
-
-                        for (param, ty_arg) in params.iter().zip(ty_args.iter()) {
-                            ret.substitute(param, ty_arg);
+                        let mut new_env = env.clone();
+                        for ((param, ty), ty_arg) in params.iter().zip(ty_args.iter()) {
+                            if ty_arg.is_const_param() {
+                                let cexpr = ty_arg.simplify_until_const_param(env, false)?;
+                                if let Some(expected_ty) = ty {
+                                    let expected = expected_ty.clone();
+                                    let found = cexpr.get_type_checked(env, i)?;
+                                    if !found.equals(expected_ty, env)? {
+                                        error!("Mismatch in expected type for constant parameter");
+                                        return Err(Error::MismatchedTypes { expected, found, expr: (cexpr.clone()).into() })
+                                    }
+                                }
+                                ret.substitute(param, ty_arg);
+                                new_env.define_const(param, cexpr.clone());
+                            } else {
+                                ret.substitute(param, ty_arg);
+                                new_env.define_type(param, ty_arg.clone());
+                            }
                         }
-                        ret.get_type_checked(env, i)?
-                            .simplify_until_type_checks(env)?
-                    }
+                        debug!("Result: {ret}");
+                        let ret = ret.get_type_checked(&new_env, i)?
+                            .simplify_until_poly(&new_env, false)?;
+                        ret
+                    }
                     _ => {
-                        // warn!("Monomorphizing non-template: {expr}");
-                        Type::Apply(Box::new(template_ty.clone()), ty_args.clone())
+                        debug!("Monomorphizing non-template: {expr}");
+                        Type::Apply(Box::new(template_ty.clone()), ty_args.clone())
                     }
                 };
 
@@ -1962,49 +2174,49 @@
         })
     }
 
-    fn substitute(&mut self, name: &str, subsitution: &Type) {
+    fn substitute(&mut self, name: &str, substitution: &Type) {
         match self {
             Self::Type(t) => {
-                *t = t.substitute(name, subsitution);
+                *t = t.substitute(name, substitution);
             }
 
             Self::Template(params, ret) => {
-                if params.contains(&name.to_string()) {
+                if params.iter().map(|x| x.0.clone()).collect::<Vec<_>>().contains(&name.to_string()) {
                     return;
                 }
-                ret.substitute(name, subsitution);
+                ret.substitute(name, substitution);
             }
             Self::Member(container, member) => {
-                container.substitute(name, subsitution);
-                member.substitute(name, subsitution);
+                container.substitute(name, substitution);
+                member.substitute(name, substitution);
             }
             Self::Annotated(expr, _) => {
-                expr.substitute(name, subsitution);
+                expr.substitute(name, substitution);
             }
             Self::As(expr, cast_ty) => {
-                expr.substitute(name, subsitution);
-                *cast_ty = cast_ty.substitute(name, subsitution);
+                expr.substitute(name, substitution);
+                *cast_ty = cast_ty.substitute(name, substitution);
             }
             Self::Declare(bindings, expr) => {
-                bindings.substitute(name, subsitution);
-                expr.substitute(name, subsitution);
+                bindings.substitute(name, substitution);
+                expr.substitute(name, substitution);
             }
             Self::Monomorphize(expr, ty_args) => {
-                expr.substitute(name, subsitution);
+                expr.substitute(name, substitution);
                 for ty_arg in ty_args {
-                    *ty_arg = ty_arg.substitute(name, subsitution);
+                    *ty_arg = ty_arg.substitute(name, substitution);
                 }
             }
             Self::TypeOf(expr) => {
-                expr.substitute(name, subsitution);
+                expr.substitute(name, substitution);
             }
             Self::Null => {}
             Self::None => {}
             Self::SizeOfType(inner_ty) => {
-                *inner_ty = inner_ty.substitute(name, subsitution);
+                *inner_ty = inner_ty.substitute(name, substitution);
             }
             Self::SizeOfExpr(expr) => {
-                expr.substitute(name, subsitution);
+                expr.substitute(name, substitution);
             }
             Self::Cell(_) => {}
             Self::Int(_) => {}
@@ -2012,49 +2224,51 @@
             Self::Char(_) => {}
             Self::Bool(_) => {}
             Self::Of(enum_type, _) => {
-                *enum_type = enum_type.substitute(name, subsitution);
+                *enum_type = enum_type.substitute(name, substitution);
             }
             Self::Tuple(items) => {
                 for item in items {
-                    item.substitute(name, subsitution);
+                    item.substitute(name, substitution);
                 }
             }
             Self::Array(items) => {
                 for item in items {
-                    item.substitute(name, subsitution);
+                    item.substitute(name, substitution);
                 }
             }
             Self::Struct(fields) => {
                 for item in fields.values_mut() {
-                    item.substitute(name, subsitution);
+                    item.substitute(name, substitution);
                 }
             }
             Self::Union(inner, _, expr) => {
-                *inner = inner.substitute(name, subsitution);
-                expr.substitute(name, subsitution);
+                *inner = inner.substitute(name, substitution);
+                expr.substitute(name, substitution);
             }
             Self::EnumUnion(inner, _, expr) => {
-                *inner = inner.substitute(name, subsitution);
-                expr.substitute(name, subsitution);
+                *inner = inner.substitute(name, substitution);
+                expr.substitute(name, substitution);
             }
             Self::PolyProc(proc) => {
-                proc.substitute(name, subsitution);
+                proc.substitute(name, substitution);
             }
             Self::Proc(proc) => {
-                proc.substitute(name, subsitution);
+                proc.substitute(name, substitution);
             }
             Self::CoreBuiltin(builtin) => {
-                builtin.substitute(name, subsitution);
+                builtin.substitute(name, substitution);
             }
             Self::StandardBuiltin(builtin) => {
-                builtin.substitute(name, subsitution);
+                builtin.substitute(name, substitution);
             }
             Self::FFIProcedure(ffi_proc) => {
-                ffi_proc.substitute(name, subsitution);
+                ffi_proc.substitute(name, substitution);
             }
-            Self::Symbol(_) => {
+            Self::Symbol(symbol_name) if symbol_name == name => {
                 // A constant symbol cannot be substituted for a type variable.
-            }
+                *self = ConstExpr::Type(substitution.clone());
+            }
+            _ => {}
         }
     }
 }
@@ -2062,10 +2276,14 @@
 impl fmt::Display for ConstExpr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
+            Self::Any => write!(f, "any"),
             Self::Template(params, expr) => {
                 write!(f, "<")?;
-                for (i, param) in params.iter().enumerate() {
+                for (i, (param, ty)) in params.iter().enumerate() {
                     write!(f, "{param}")?;
+                    if let Some(ty) = ty {
+                        write!(f, ": {ty}")?;
+                    }
                     if i < params.len() - 1 {
                         write!(f, ", ")?
                     }
@@ -2186,10 +2404,11 @@
                 container.hash(state);
                 member.hash(state);
             }
-            Self::Annotated(expr, _) => {
+            Self::Annotated(expr, _metadata) => {
                 state.write_u8(3);
                 expr.hash(state);
-            }
+                // metadata.hash(state);
+            }
             Self::FFIProcedure(ffi_proc) => {
                 state.write_u8(4);
                 ffi_proc.hash(state);
@@ -2296,9 +2515,27 @@
                 state.write_u8(28);
                 ty.hash(state);
             }
+            Self::Any => state.write_u8(29),
         }
     }
 }
 
 impl Eq for ConstExpr {}
-
\ No newline at end of file + +impl From<PolyProcedure> for ConstExpr { + fn from(value: PolyProcedure) -> Self { + Self::PolyProc(value) + } +} + +impl From<Procedure> for ConstExpr { + fn from(value: Procedure) -> Self { + Self::Proc(value) + } +} + +impl From<Type> for ConstExpr { + fn from(value: Type) -> Self { + Self::Type(value) + } +} \ No newline at end of file diff --git a/docs/src/sage/lir/expr/declaration.rs.html b/docs/src/sage/lir/expr/declaration.rs.html index 030490cb..7414f5d4 100644 --- a/docs/src/sage/lir/expr/declaration.rs.html +++ b/docs/src/sage/lir/expr/declaration.rs.html @@ -1001,15 +1001,6 @@ 1000 1001 1002 -1003 -1004 -1005 -1006 -1007 -1008 -1009 -1010 -1011
use super::{PolyProcedure, Procedure};
 use crate::{
     asm::{AssemblyProgram, CoreOp, Location, SP},
@@ -1247,7 +1238,7 @@
                 expr.clone().compile_expr(env, output)?;
 
                 // Add the variable to the environment, so that it can be used in the body.
-                env.add_local_variable_declaration(self)?;
+                env.add_local_variable_declaration(self, true)?;
                 // Log the instructions for the declaration.
                 output.log_instructions_after(name, &log_message, current_instruction);
             }
@@ -1523,10 +1514,7 @@
                 let bindings = pat.get_bindings(expr, &ty, env)?;
                 // Get the size of all the bindings
                 let size_of_bindings = bindings
-                    // .iter()
-                    // .map(|(_name, (_mut, ty))| ty.get_size(env).unwrap_or(0))
-                    // .sum::<usize>();
-                    .values()
+                    .values()
                     .collect::<Vec<_>>()
                     .par_iter()
                     .map(|(_mut, ty)| ty.get_size(env).unwrap_or(0))
@@ -1583,7 +1571,7 @@
 
                     for (name, associated_const) in impls {
                         let templated_const =
-                            associated_const.template(supplied_param_symbols.clone());
+                            associated_const.template(template_params.clone().into_iter().zip(supplied_param_symbols.clone().into_iter()).map(|((_, ty), param)| (param, ty)).collect());
                         new_env.add_associated_const(
                             *template.clone(),
                             name,
@@ -1596,10 +1584,6 @@
 
                     // If we are at the limit of parallel recursion, then we should
                     // type check the associated constants sequentially.
-                    // for templated_const in templated_consts {
-                    //     templated_const.type_check(&new_env)?;
-                    // }
-
                     templated_consts
                         .par_iter()
                         .try_for_each(|templated_const| templated_const.type_check(&new_env))?;
@@ -1618,7 +1602,7 @@
             Self::Many(decls) => {
                 let mut new_env = env.clone();
                 // Add all the compile-time declarations to the environment.
-                new_env.add_declaration(&self.clone())?;
+                new_env.add_declaration(&self.clone(), false)?;
 
                 // Get all the compile time declarations so we can type check them in parallel.
                 let (comp_time_decls, run_time_decls): (Vec<_>, Vec<_>) = decls
@@ -1638,7 +1622,7 @@
                     // .map(|decl| decl.type_check(&new_env))
                     .try_for_each(|decl| {
                         decl.type_check(&new_env)?;
-                        new_env.add_declaration(decl)
+                        new_env.add_declaration(decl, false)
                     })?;
 
                 /*
@@ -1684,16 +1668,14 @@
                 let mut new_env = env.clone();
 
                 // Add all the compile-time declarations to the environment.
-                // new_env.add_compile_time_declaration(&Self::Many(decls.clone()))?;
-                new_env.add_declaration(&Self::Many(decls.clone()))?;
+                new_env.add_declaration(&Self::Many(decls.clone()), false)?;
                 trace!("Typechecking module {}", name);
                 // Get all the compile time declarations so we can type check them in parallel.
                 let (comp_time_decls, _run_time_decls): (Vec<_>, Vec<_>) = decls
                     .iter()
                     .partition(|decl| decl.is_compile_time_declaration());
 
-                // trace!("Compile time declarations: {:?}", comp_time_decls);
-                if !comp_time_decls.is_empty() {
+                if !comp_time_decls.is_empty() {
                     // Type check all the compile time declarations in parallel.
                     comp_time_decls
                         .par_iter()
diff --git a/docs/src/sage/lir/expr/expression.rs.html b/docs/src/sage/lir/expr/expression.rs.html
index a2435d89..7497d158 100644
--- a/docs/src/sage/lir/expr/expression.rs.html
+++ b/docs/src/sage/lir/expr/expression.rs.html
@@ -1152,31 +1152,6 @@
 1151
 1152
 1153
-1154
-1155
-1156
-1157
-1158
-1159
-1160
-1161
-1162
-1163
-1164
-1165
-1166
-1167
-1168
-1169
-1170
-1171
-1172
-1173
-1174
-1175
-1176
-1177
-1178
 
//! # Expression
 //!
 //! An expression is a runtime value.
@@ -1415,8 +1390,7 @@
 
                                 // Check if the value actually has a member with this name.
                                 let val_type = val.get_type(env)?;
-                                // val_type.add_monomorphized_associated_consts(env)?;
-                                trace!(target: "member", "got value type: {:#?}: {val}.{name}", val_type);
+                                trace!(target: "member", "got value type: {:#?}: {val}.{name}", val_type);
                                 // If the value has a member with this name,
                                 trace!(target: "member", "WHOOP WHOOP");
                                 let (mut associated_function, mut associated_function_type) = env
@@ -1425,23 +1399,14 @@
                                         error!(target: "member", "Symbol not defined: {name} while getting member");
                                         Error::SymbolNotDefined(name.clone())
                                 })?;
-                                // .monomorphize(ty_args.clone());
-                                associated_function =
+                                associated_function =
                                     associated_function.monomorphize(ty_args.clone());
                                 associated_function_type =
                                     associated_function_type.apply(ty_args.clone());
-                                // let associated_function = ConstExpr::Type(val_type.clone())
-                                //     .field(*member)
-                                //     .monomorphize(ty_args.clone());
-                                trace!(target: "member", "function value: {associated_function} in {env}");
-                                // Get the type of the function
-                                // let associated_function_type = env
-                                //     .get_type_of_associated_const(&val_type, &name)
-                                //     .ok_or_else(|| Error::SymbolNotDefined(name))?
-                                //     .apply(ty_args);
-                                // trace!(target: "member", "got function type: {}", associated_function_type);
-
-                                let mut new_args = vec![];
+
+                                trace!(target: "member", "function value: {associated_function} in {env}");
+
+                                let mut new_args = vec![];
                                 if let Some(expected_mutability) =
                                     associated_function_type.get_self_param_mutability(env)
                                 {
@@ -1492,8 +1457,7 @@
                             let name = name?;
                             // Check if the value actually has a member with this name.
                             let val_type = val.get_type(env)?;
-                            // val_type.add_monomorphized_associated_consts(env)?;
-                            trace!(target: "member", "got value type: {:#?}: {val}.{name}", val_type);
+                            trace!(target: "member", "got value type: {:#?}: {val}.{name}", val_type);
                             // If the value has a member with this name,
                             trace!(target: "member", "WHOOP WHOOP");
 
@@ -1504,18 +1468,9 @@
                                     Error::SymbolNotDefined(name.clone())
                                 })?;
 
-                            // let associated_function = env
-                            //     .get_associated_const(&val_type, &name)
-                            //     .ok_or_else(|| Error::SymbolNotDefined(name.clone()))?;
-                            // let associated_function = ConstExpr::Type(val_type.clone())
-                            //     .field(*member)
-                            //     .monomorphize(ty_args.clone());
-                            trace!(target: "member", "function value: {associated_function} in {env}");
+                            trace!(target: "member", "function value: {associated_function} in {env}");
 
                             // Get the type of the function
-                            // let associated_function_type = env
-                            //     .get_type_of_associated_const(&val_type, &name)
-                            //     .ok_or_else(|| Error::SymbolNotDefined(name))?;
                             trace!(target: "member", "got function type: {}", associated_function_type);
                             // Get the first argument's type
                             let mut new_args = vec![];
@@ -1564,8 +1519,7 @@
                             let name = name?;
                             // Check if the value actually has a member with this name.
                             let val_type = val.get_type(env)?;
-                            // val_type.add_monomorphized_associated_consts(env)?;
-                            trace!(target: "member", "got value type: {:#?}: {val}.{name}", val_type);
+                            trace!(target: "member", "got value type: {:#?}: {val}.{name}", val_type);
                             // If the value has a member with this name,
                             trace!(target: "member", "WHOOP WHOOP");
                             let (associated_function, associated_function_type) = env
@@ -1577,10 +1531,6 @@
                             trace!(target: "member", "function value: {associated_function} in {env}");
 
                             // Get the type of the function
-                            // let associated_function_type = env
-                            //     .get_type_of_associated_const(&val_type, &name)
-                            //     .ok_or_else(|| Error::SymbolNotDefined(name))?
-                            //     .clone();
                             trace!(target: "member", "got function type: {}", associated_function_type);
                             // Get the first argument's type
                             let mut new_args = vec![];
diff --git a/docs/src/sage/lir/expr/ops/arithmetic/mod.rs.html b/docs/src/sage/lir/expr/ops/arithmetic/mod.rs.html
index 5a75c766..6cf9aa79 100644
--- a/docs/src/sage/lir/expr/ops/arithmetic/mod.rs.html
+++ b/docs/src/sage/lir/expr/ops/arithmetic/mod.rs.html
@@ -397,6 +397,51 @@
 396
 397
 398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
 
//! # Arithmetic Operations
 //!
 //! This module implements several arithmetic operations:
@@ -431,6 +476,147 @@
 }
 
 impl BinaryOp for Arithmetic {
+    /// Compiles the operation on the given expressions.
+    fn compile(
+        &self,
+        lhs: &Expr,
+        rhs: &Expr,
+        env: &mut Env,
+        output: &mut dyn AssemblyProgram,
+    ) -> Result<(), Error> {
+        if let Expr::Annotated(lhs, metadata) = lhs {
+            return self
+                .compile(lhs, rhs, env, output)
+                .map_err(|err| err.annotate(metadata.clone()));
+        }
+        if let Expr::Annotated(rhs, metadata) = rhs {
+            return self
+                .compile(lhs, rhs, env, output)
+                .map_err(|err| err.annotate(metadata.clone()));
+        }
+
+        // trace!("Compiling binary op: {lhs} {self} {rhs} ({self:?})");
+        lhs.clone().compile_expr(env, output)?;
+        rhs.clone().compile_expr(env, output)?;
+        // self.compile_types(&, &rhs.get_type(env)?, env, output)?;
+        let lhs_expr = lhs;
+        let rhs_expr = rhs;
+        let lhs = &lhs_expr.get_type(env)?;
+        let rhs = &rhs_expr.get_type(env)?;
+
+        if let (Type::Array(_, _), Arithmetic::Multiply, Type::Int) = (lhs, self, rhs) {
+            if !rhs.equals(&Type::Int, env)? {
+                return Err(Error::MismatchedTypes { expected: Type::Int, found: rhs.clone(), expr: rhs_expr.clone() })
+            }
+
+            // Copy the loop RHS times.
+            // This will just evaluate the array, evaluate the int, and then repeatedly
+            // copy the array back onto the stack `rhs` times.
+            let arr_size = lhs.get_size(env)?;
+            // Copy the integer into a register.
+            output.op(CoreOp::Many(vec![
+                // Pop into B
+                CoreOp::Pop(Some(B), 1),
+                // Store the address of the array in A.
+                CoreOp::GetAddress {
+                    addr: SP.deref().offset(1 - arr_size as isize),
+                    dst: A,
+                },
+                // While B != 0
+                CoreOp::Dec(B),
+                CoreOp::While(B),
+                // Push the array back onto the stack, starting at A
+                CoreOp::Push(A.deref(), arr_size),
+                // Decrement B
+                CoreOp::Dec(B),
+                CoreOp::End,
+            ]));
+
+            return Ok(());
+        }
+
+        let src = SP.deref();
+        let dst = SP.deref().offset(-1);
+        let tmp = SP.deref().offset(1);
+        // Get the respective core operation for the current expression.
+        let core_op = match self {
+            Self::Add => CoreOp::Add { src, dst },
+            Self::Subtract => CoreOp::Sub { src, dst },
+            Self::Multiply => CoreOp::Mul { src, dst },
+            Self::Divide => CoreOp::Div { src, dst },
+            Self::Remainder => CoreOp::Rem { src, dst },
+            Self::Power => CoreOp::Many(vec![
+                // We can't use the `Pow` operation, because it's not supported by
+                // the core variant. So we have to do it with a loop.
+                CoreOp::Move {
+                    src: dst.clone(),
+                    dst: tmp.clone(),
+                },
+                CoreOp::Set(dst.clone(), 1),
+                CoreOp::While(src.clone()),
+                CoreOp::Mul { src: tmp, dst },
+                CoreOp::Dec(src),
+                CoreOp::End,
+            ]),
+        };
+        let src = SP.deref();
+        let dst = SP.deref().offset(-1);
+        // Get the respective standard operation for the current expression.
+        let std_op = match self {
+            Self::Add => StandardOp::Add { src, dst },
+            Self::Subtract => StandardOp::Sub { src, dst },
+            Self::Multiply => StandardOp::Mul { src, dst },
+            Self::Divide => StandardOp::Div { src, dst },
+            Self::Remainder => StandardOp::Rem { src, dst },
+            Self::Power => StandardOp::Pow { src, dst },
+        };
+        // Now, perform the correct assembly expressions based on the types of the two expressions.
+        match (lhs, rhs) {
+            // If a `Float` and a `Cell` are used, we just interpret the `Cell` as a `Float`.
+            (Type::Cell, Type::Float) | (Type::Float, Type::Cell) => {
+                output.std_op(std_op)?;
+            }
+            // Two floats are used as floats.
+            (Type::Float, Type::Float) => {
+                output.std_op(std_op)?;
+            }
+            // An integer used with a float is promoted, and returns a float.
+            (Type::Int, Type::Float) => {
+                output.std_op(StandardOp::ToFloat(SP.deref().offset(-1)))?;
+                output.std_op(std_op)?;
+            }
+            (Type::Float, Type::Int) => {
+                output.std_op(StandardOp::ToFloat(SP.deref()))?;
+                output.std_op(std_op)?;
+            }
+
+            // If cells and/or ints are used, we just use them as integers.
+            (Type::Int, Type::Int)
+            | (Type::Cell, Type::Cell)
+            | (Type::Cell, Type::Int)
+            | (Type::Int, Type::Cell) => {
+                output.op(core_op);
+            }
+
+            (Type::Unit(_name1, a_type), Type::Unit(_name2, b_type)) => {
+                return self.compile_types(a_type, b_type, env, output);
+            }
+
+            // Cannot do arithmetic on other pairs of types.
+            _ => {
+                return Err(Error::InvalidBinaryOpTypes(
+                    Box::new(*self),
+                    lhs.clone(),
+                    rhs.clone(),
+                ))
+            }
+        }
+        // Pop `b` off of the stack: we only needed it to evaluate
+        // the arithmetic and store the result to `a` on the stack.
+        output.op(CoreOp::Pop(None, 1));
+        Ok(())
+    }
+
     /// Can this binary operation be applied to the given types?
     fn can_apply(&self, lhs: &Type, rhs: &Type, env: &Env) -> Result<bool, Error> {
         match (lhs, rhs) {
@@ -439,6 +625,7 @@
                 Ok(true)
             }
             (Type::Array(_, _), Type::Int) => Ok(matches!(self, Self::Multiply)),
+            (Type::Array(_, _), Type::Type(..)) => Ok(matches!(self, Self::Multiply)),
 
             (Type::Int | Type::Float | Type::Cell, Type::Cell)
             | (Type::Cell, Type::Int | Type::Float) => Ok(true),
@@ -474,8 +661,10 @@
                 .return_type(lhs, rhs, env)
                 .map_err(|e| e.annotate(metadata.clone()));
         }
+        let lhs_ty = lhs.get_type(env)?;
+        let rhs_ty = rhs.get_type(env)?;
 
-        Ok(match (lhs.get_type(env)?, rhs.get_type(env)?) {
+        let result = Ok(match (lhs_ty.discard_type_wrapper(), rhs_ty.discard_type_wrapper()) {
             (Type::Int, Type::Int) => Type::Int,
             (Type::Int, Type::Float) | (Type::Float, Type::Int) | (Type::Float, Type::Float) => {
                 Type::Float
@@ -483,19 +672,22 @@
             (Type::Int | Type::Float | Type::Cell, Type::Cell)
             | (Type::Cell, Type::Int | Type::Float) => Type::Cell,
 
-            (Type::Array(elem, size), Type::Int) => {
+            (Type::Array(elem, size), _other) => {
                 if let (Self::Multiply, Expr::ConstExpr(const_rhs)) = (self, rhs) {
                     let size = size.as_int(env)?;
-                    let n = const_rhs.clone().as_int(env)?;
-                    if n <= 0 {
-                        error!("Cannot multiply array {lhs} by {n} (not positive)");
-                        return Err(Error::InvalidBinaryOp(
-                            Box::new(*self),
-                            lhs.clone(),
-                            rhs.clone(),
-                        ));
+                    if let Ok(n) = const_rhs.clone().as_int(env) {
+                        if n <= 0 {
+                            error!("Cannot multiply array {lhs} by {n} (not positive)");
+                            return Err(Error::InvalidBinaryOp(
+                                Box::new(*self),
+                                lhs.clone(),
+                                rhs.clone(),
+                            ));
+                        }
+                        Type::Array(elem, Box::new(ConstExpr::Int(size * n)))
+                    } else {
+                        Type::Array(elem, Box::new(ConstExpr::Any))
                     }
-                    Type::Array(elem, Box::new(ConstExpr::Int(size * n)))
                 } else {
                     error!("Cannot multiply array {lhs} by {rhs} (not constant = {rhs:?})");
                     return Err(Error::InvalidBinaryOp(
@@ -519,6 +711,7 @@
             (Type::Unit(name1, a_type), Type::Unit(name2, b_type)) => {
                 // Make sure that the two units are the same.
                 if name1 != name2 {
+                    error!("{name1} is not {name2}");
                     return Err(Error::InvalidBinaryOp(
                         Box::new(*self),
                         lhs.clone(),
@@ -528,6 +721,7 @@
 
                 // Make sure that inner types are compatible.
                 if !a_type.equals(&b_type, env)? {
+                    error!("{a_type} is not {b_type}");
                     return Err(Error::InvalidBinaryOp(
                         Box::new(*self),
                         lhs.clone(),
@@ -537,14 +731,16 @@
 
                 Type::Unit(name1, a_type)
             }
-            _ => {
+            (a, b) => {
+                error!("Unhandled case {a} {self} {b}");
                 return Err(Error::InvalidBinaryOp(
                     Box::new(*self),
                     lhs.clone(),
                     rhs.clone(),
                 ))
             }
-        })
+        });
+        result
     }
 
     /// Evaluate this binary operation on the given constant values.
@@ -651,117 +847,11 @@
     /// Compile the binary operation.
     fn compile_types(
         &self,
-        lhs: &Type,
-        rhs: &Type,
-        env: &mut Env,
-        output: &mut dyn AssemblyProgram,
+        _lhs: &Type,
+        _rhs: &Type,
+        _env: &mut Env,
+        _output: &mut dyn AssemblyProgram,
     ) -> Result<(), Error> {
-        if let (Type::Array(_, _), Arithmetic::Multiply, Type::Int) = (lhs, self, rhs) {
-            // Copy the loop RHS times.
-            // This will just evaluate the array, evaluate the int, and then repeatedly
-            // copy the array back onto the stack `rhs` times.
-            let arr_size = lhs.get_size(env)?;
-            // Copy the integer into a register.
-            output.op(CoreOp::Many(vec![
-                // Pop into B
-                CoreOp::Pop(Some(B), 1),
-                // Store the address of the array in A.
-                CoreOp::GetAddress {
-                    addr: SP.deref().offset(1 - arr_size as isize),
-                    dst: A,
-                },
-                // While B != 0
-                CoreOp::Dec(B),
-                CoreOp::While(B),
-                // Push the array back onto the stack, starting at A
-                CoreOp::Push(A.deref(), arr_size),
-                // Decrement B
-                CoreOp::Dec(B),
-                CoreOp::End,
-            ]));
-
-            return Ok(());
-        }
-
-        let src = SP.deref();
-        let dst = SP.deref().offset(-1);
-        let tmp = SP.deref().offset(1);
-        // Get the respective core operation for the current expression.
-        let core_op = match self {
-            Self::Add => CoreOp::Add { src, dst },
-            Self::Subtract => CoreOp::Sub { src, dst },
-            Self::Multiply => CoreOp::Mul { src, dst },
-            Self::Divide => CoreOp::Div { src, dst },
-            Self::Remainder => CoreOp::Rem { src, dst },
-            Self::Power => CoreOp::Many(vec![
-                // We can't use the `Pow` operation, because it's not supported by
-                // the core variant. So we have to do it with a loop.
-                CoreOp::Move {
-                    src: dst.clone(),
-                    dst: tmp.clone(),
-                },
-                CoreOp::Set(dst.clone(), 1),
-                CoreOp::While(src.clone()),
-                CoreOp::Mul { src: tmp, dst },
-                CoreOp::Dec(src),
-                CoreOp::End,
-            ]),
-        };
-        let src = SP.deref();
-        let dst = SP.deref().offset(-1);
-        // Get the respective standard operation for the current expression.
-        let std_op = match self {
-            Self::Add => StandardOp::Add { src, dst },
-            Self::Subtract => StandardOp::Sub { src, dst },
-            Self::Multiply => StandardOp::Mul { src, dst },
-            Self::Divide => StandardOp::Div { src, dst },
-            Self::Remainder => StandardOp::Rem { src, dst },
-            Self::Power => StandardOp::Pow { src, dst },
-        };
-        // Now, perform the correct assembly expressions based on the types of the two expressions.
-        match (lhs, rhs) {
-            // If a `Float` and a `Cell` are used, we just interpret the `Cell` as a `Float`.
-            (Type::Cell, Type::Float) | (Type::Float, Type::Cell) => {
-                output.std_op(std_op)?;
-            }
-            // Two floats are used as floats.
-            (Type::Float, Type::Float) => {
-                output.std_op(std_op)?;
-            }
-            // An integer used with a float is promoted, and returns a float.
-            (Type::Int, Type::Float) => {
-                output.std_op(StandardOp::ToFloat(SP.deref().offset(-1)))?;
-                output.std_op(std_op)?;
-            }
-            (Type::Float, Type::Int) => {
-                output.std_op(StandardOp::ToFloat(SP.deref()))?;
-                output.std_op(std_op)?;
-            }
-
-            // If cells and/or ints are used, we just use them as integers.
-            (Type::Int, Type::Int)
-            | (Type::Cell, Type::Cell)
-            | (Type::Cell, Type::Int)
-            | (Type::Int, Type::Cell) => {
-                output.op(core_op);
-            }
-
-            (Type::Unit(_name1, a_type), Type::Unit(_name2, b_type)) => {
-                return self.compile_types(a_type, b_type, env, output);
-            }
-
-            // Cannot do arithmetic on other pairs of types.
-            _ => {
-                return Err(Error::InvalidBinaryOpTypes(
-                    Box::new(*self),
-                    lhs.clone(),
-                    rhs.clone(),
-                ))
-            }
-        }
-        // Pop `b` off of the stack: we only needed it to evaluate
-        // the arithmetic and store the result to `a` on the stack.
-        output.op(CoreOp::Pop(None, 1));
         Ok(())
     }
 
diff --git a/docs/src/sage/lir/expr/ops/comparison.rs.html b/docs/src/sage/lir/expr/ops/comparison.rs.html
index d204c26a..ef467f8e 100644
--- a/docs/src/sage/lir/expr/ops/comparison.rs.html
+++ b/docs/src/sage/lir/expr/ops/comparison.rs.html
@@ -315,7 +315,7 @@
 impl BinaryOp for Comparison {
     /// Can this binary operation be applied to the given types?
     fn can_apply(&self, lhs: &Type, rhs: &Type, env: &Env) -> Result<bool, Error> {
-        match (lhs, self, rhs) {
+        match (&lhs.clone().discard_type_wrapper(), self, &rhs.clone().discard_type_wrapper()) {
             (Type::Int, Self::LessThan, Type::Int)
             | (Type::Int, Self::LessThanOrEqual, Type::Int)
             | (Type::Int, Self::GreaterThan, Type::Int)
@@ -490,7 +490,7 @@
         let dst = SP.deref().offset(-1);
         let tmp = SP.deref().offset(1);
         // Now, perform the correct assembly expressions based on the types of the two expressions.
-        match (lhs, self, rhs) {
+        match (&lhs.clone().discard_type_wrapper(), self, &rhs.clone().discard_type_wrapper()) {
             // If a `Float` and a `Cell` are used, we just interpret the `Cell` as a `Float`.
             (Type::Cell, _, Type::Float) | (Type::Float, _, Type::Cell) => {
                 output.op(CoreOp::Move { src: dst, dst: tmp });
diff --git a/docs/src/sage/lir/expr/ops/io.rs.html b/docs/src/sage/lir/expr/ops/io.rs.html
index 62b562ef..c5f5f856 100644
--- a/docs/src/sage/lir/expr/ops/io.rs.html
+++ b/docs/src/sage/lir/expr/ops/io.rs.html
@@ -642,6 +642,7 @@
 641
 642
 643
+644
 
use super::*;
 
 use crate::{
@@ -651,13 +652,14 @@
 };
 use ::core::fmt::{Debug, Display, Formatter, Result as FmtResult};
 
+
 #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
 pub struct Get;
 
 impl UnaryOp for Get {
     /// Can this unary operation be applied to the given type?
     fn can_apply(&self, ty: &Type, env: &Env) -> Result<bool, Error> {
-        ty.simplify_until_concrete(env).map(|ty| {
+        ty.simplify_until_concrete(env, false).map(|ty| {
             if let Type::Pointer(mutability, x) = ty {
                 match *x {
                     Type::Char | Type::Int | Type::Float => mutability.is_mutable(),
@@ -744,7 +746,7 @@
         env: &mut Env,
         output: &mut dyn AssemblyProgram,
     ) -> Result<(), Error> {
-        let t = &t.simplify_until_concrete(env)?;
+        let t = &t.simplify_until_concrete(env, false)?;
         match t {
             Type::Type(t) => {
                 for c in format!("{}", t).chars() {
@@ -1074,7 +1076,7 @@
         env: &mut Env,
         output: &mut dyn AssemblyProgram,
     ) -> Result<(), Error> {
-        let t = &t.simplify_until_concrete(env)?;
+        let t = &t.simplify_until_concrete(env, false)?;
         match t {
             Type::Cell => {
                 output.op(CoreOp::Put(addr, Output::stdout_int()));
@@ -1241,7 +1243,7 @@
         // Get the size of the type.
         let size = ty.get_size(env)? as isize;
 
-        let ty = &ty.simplify_until_concrete(env)?;
+        let ty = &ty.simplify_until_concrete(env, false)?;
 
         // Calculate the address of the expression on the stack.
         let addr = SP.deref().offset(-size + 1);
diff --git a/docs/src/sage/lir/expr/ops/mod.rs.html b/docs/src/sage/lir/expr/ops/mod.rs.html
index 3b351c7e..5bbb6d64 100644
--- a/docs/src/sage/lir/expr/ops/mod.rs.html
+++ b/docs/src/sage/lir/expr/ops/mod.rs.html
@@ -612,6 +612,7 @@
 611
 612
 613
+614
 
//! # Operations
 //!
 //! This module contains implementations of various
@@ -925,6 +926,7 @@
         self.compile_types(&lhs.get_type(env)?, &rhs.get_type(env)?, env, output)?;
         Ok(())
     }
+    
     /// Compiles the operation on the given types. (Generates the code for the operation.)
     fn compile_types(
         &self,
diff --git a/docs/src/sage/lir/expr/ops/tagged_union.rs.html b/docs/src/sage/lir/expr/ops/tagged_union.rs.html
index fb941a8b..00274918 100644
--- a/docs/src/sage/lir/expr/ops/tagged_union.rs.html
+++ b/docs/src/sage/lir/expr/ops/tagged_union.rs.html
@@ -186,12 +186,12 @@
     /// Can this unary operation be applied to the given type?
     fn can_apply(&self, ty: &Type, env: &Env) -> Result<bool, Error> {
         let ty = ty.clone().simplify(env)?;
-        Ok(ty.simplify_until_has_variants(env).is_ok())
+        Ok(ty.simplify_until_has_variants(env, false).is_ok())
     }
 
     /// Get the type of the result of applying this unary operation to the given type.
     fn return_type(&self, expr: &Expr, env: &Env) -> Result<Type, Error> {
-        let ty = expr.get_type(env)?.simplify_until_has_variants(env)?;
+        let ty = expr.get_type(env)?.simplify_until_has_variants(env, false)?;
 
         match ty {
             Type::EnumUnion(variants) => Ok(Type::Enum(variants.into_keys().collect())),
@@ -275,12 +275,12 @@
     /// Can this unary operation be applied to the given type?
     fn can_apply(&self, ty: &Type, env: &Env) -> Result<bool, Error> {
         let ty = ty.clone().simplify(env)?;
-        Ok(ty.simplify_until_has_variants(env).is_ok())
+        Ok(ty.simplify_until_has_variants(env, false).is_ok())
     }
 
     /// Get the type of the result of applying this unary operation to the given type.
     fn return_type(&self, expr: &Expr, env: &Env) -> Result<Type, Error> {
-        let ty = expr.get_type(env)?.simplify_until_has_variants(env)?;
+        let ty = expr.get_type(env)?.simplify_until_has_variants(env, false)?;
 
         match ty {
             Type::EnumUnion(variants) => Ok(Type::Union(variants)),
diff --git a/docs/src/sage/lir/expr/pattern.rs.html b/docs/src/sage/lir/expr/pattern.rs.html
index c0ad1e53..6d599560 100644
--- a/docs/src/sage/lir/expr/pattern.rs.html
+++ b/docs/src/sage/lir/expr/pattern.rs.html
@@ -1164,14 +1164,14 @@
         env: &Env,
     ) -> Result<Type, Error> {
         // Get the type of the expression being matched.
-        let ty = expr.get_type(env)?.simplify_until_concrete(env)?;
+        let ty = expr.get_type(env)?.simplify_until_concrete(env, false)?;
         // Get the bindings for the pattern.
         let bindings = self.get_bindings(expr, &ty, env)?;
         // Create a new environment with the bindings.
         let mut new_env = env.clone();
         for (var, (mutabilty, ty)) in bindings {
             // Define the variables in the new environment.
-            new_env.define_var(var, mutabilty, ty)?;
+            new_env.define_var(var, mutabilty, ty, true)?;
         }
 
         // Get the type of the branch.
@@ -1192,7 +1192,7 @@
         matching_expr_ty: &Type,
         env: &Env,
     ) -> Result<bool, Error> {
-        let matching_expr_ty = &matching_expr_ty.simplify_until_concrete(env)?;
+        let matching_expr_ty = &matching_expr_ty.simplify_until_concrete(env, false)?;
         match matching_expr_ty {
             Type::Bool => {
                 // If the type is a boolean, the patterns are exhaustive if they match both `true` and `false`.
@@ -1483,7 +1483,7 @@
     pub fn type_check(&self, matching_expr: &Expr, branch: &Expr, env: &Env) -> Result<(), Error> {
         trace!("Type checking pattern match: {} => {}", self, branch);
         // Get the type of the expression being matched.
-        let matching_ty = matching_expr.get_type(env)?.simplify_until_concrete(env)?;
+        let matching_ty = matching_expr.get_type(env)?.simplify_until_concrete(env, false)?;
         // Get the type of the branch as a result of the match.
         let expected = self.get_branch_result_type(matching_expr, branch, env)?;
         // Type-check the expression generated to match the pattern.
@@ -1592,9 +1592,9 @@
         // Create a new environment with the bindings
         let mut new_env = env.clone();
         // Get the type of the expression being matched
-        let match_type = expr.get_type(env)?.simplify_until_concrete(env)?;
+        let match_type = expr.get_type(env)?.simplify_until_concrete(env, false)?;
         // Define the variable in the new environment.
-        new_env.define_var(var_name.clone(), Mutability::Immutable, match_type.clone())?;
+        new_env.define_var(var_name.clone(), Mutability::Immutable, match_type.clone(), true)?;
         // Generate the expression which evaluates the `match` expression.
         let match_expr = Pattern::match_pattern_helper(&Expr::var(&var_name), branches, &new_env)?;
 
@@ -1664,7 +1664,7 @@
         env: &Env,
         mut origin: usize,
     ) -> Result<HashMap<String, (Mutability, Type, usize)>, Error> {
-        let ty = &ty.simplify_until_concrete(env)?;
+        let ty = &ty.simplify_until_concrete(env, false)?;
         Ok(match (self, ty) {
             // If the pattern is a tuple, and the type is a tuple, then
             // get the bindings for each element of the tuple.
@@ -1813,7 +1813,7 @@
     /// Does this pattern match the given expression?
     /// This function returns an expression which evaluates to true if the expression matches the pattern.
     fn matches(&self, expr: &Expr, ty: &Type, env: &Env) -> Result<Expr, Error> {
-        let ty = &ty.simplify_until_concrete(env)?;
+        let ty = &ty.simplify_until_concrete(env, false)?;
         Ok(match (self, ty) {
             // If the pattern is a variant, and the type is a EnumUnion,
             // check if the variant matches the pattern.
@@ -1973,7 +1973,7 @@
     /// then this will not work correctly. This function does not check the arguments.***
     pub fn declare_let_bind(&self, expr: &Expr, ty: &Type, env: &mut Env) -> Result<(), Error> {
         // Get the type of the expression being matched.
-        let ty = &ty.simplify_until_concrete(env)?;
+        let ty = &ty.simplify_until_concrete(env, false)?;
         // Get the variable bindings for the pattern.
         // This tells us the type and mutability of each variable.
         let bindings = self.get_bindings_with_offset(expr, ty, env, 0)?;
@@ -1984,7 +1984,7 @@
         bindings.sort_by_key(|(_, (_, _, offset))| *offset);
         // Define all the bindings in the environment.
         for (name, (mutability, ty, _)) in &bindings {
-            env.define_var(name, *mutability, ty.clone())?;
+            env.define_var(name, *mutability, ty.clone(), true)?;
         }
         Ok(())
     }
@@ -1999,7 +1999,7 @@
     /// added to the environment, and will be bound to the corresponding value in
     /// the expression which is being matched.
     fn bind(&self, expr: &Expr, ty: &Type, ret: &Expr, env: &Env) -> Result<Expr, Error> {
-        let ty = &ty.simplify_until_concrete(env)?;
+        let ty = &ty.simplify_until_concrete(env, false)?;
         Ok(match (self, ty) {
             // If the pattern is a variant, and the type is a tagged union,
             // bind the pattern to the corresponding variant type in the tagged union.
diff --git a/docs/src/sage/lir/expr/procedure/mono.rs.html b/docs/src/sage/lir/expr/procedure/mono.rs.html
index f5ac600e..9f122f38 100644
--- a/docs/src/sage/lir/expr/procedure/mono.rs.html
+++ b/docs/src/sage/lir/expr/procedure/mono.rs.html
@@ -457,7 +457,7 @@
 
         // Create a new scope for the procedure's body, and define the arguments for the scope.
         let mut new_env = env.new_scope();
-        new_env.define_args(self.args.clone())?;
+        new_env.define_args(self.args.clone(), false)?;
         new_env.set_expected_return_type(self.ret.clone());
 
         // Get the type of the procedure's body, and confirm that it matches the return type.
@@ -507,7 +507,7 @@
         let mut new_env = env.new_scope();
 
         // Declare the arguments and get their size
-        let args_size = new_env.define_args(self.args)?;
+        let args_size = new_env.define_args(self.args, true)?;
         // Get the size of the return value to leave on the stack
         let ret_size = self.ret.get_size(env)?;
 
diff --git a/docs/src/sage/lir/expr/procedure/poly.rs.html b/docs/src/sage/lir/expr/procedure/poly.rs.html
index 9a1e84c3..b41d862d 100644
--- a/docs/src/sage/lir/expr/procedure/poly.rs.html
+++ b/docs/src/sage/lir/expr/procedure/poly.rs.html
@@ -300,6 +300,30 @@
 299
 300
 301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
 
//! # Poly-Procedure
 //!
 //! A polymorphic procedure of LIR code which can be applied to a list of arguments with type arguments.
@@ -314,7 +338,7 @@
 };
 use std::{hash::Hash, hash::Hasher};
 
-use log::{debug, error, trace};
+use log::{debug, error};
 use serde_derive::{Deserialize, Serialize};
 
 /// A polymorphic procedure of LIR code which can be applied to a list of arguments with type arguments.
@@ -325,7 +349,7 @@
     /// The name of the procedure.
     name: String,
     /// The type parameters of the procedure.
-    ty_params: Vec<String>,
+    ty_params: Vec<(String, Option<Type>)>,
     /// The arguments of the procedure.
     args: Vec<(String, Mutability, Type)>,
     /// The return type of the procedure.
@@ -354,7 +378,7 @@
     /// a return type, and the body of the procedure.
     pub fn new(
         name: String,
-        ty_params: Vec<String>,
+        ty_params: Vec<(String, Option<Type>)>,
         args: Vec<(String, Mutability, Type)>,
         ret: Type,
         body: impl Into<Expr>,
@@ -379,7 +403,11 @@
         }
     }
 
-    pub fn from_mono(mono: Procedure, ty_params: Vec<String>) -> Self {
+    pub fn get_type_params(&self) -> &Vec<(String, Option<Type>)> {
+        &self.ty_params
+    }
+
+    pub fn from_mono(mono: Procedure, ty_params: Vec<(String, Option<Type>)>) -> Self {
         debug!(target: "mono", "Creating polymorphic procedure from monomorph {}", mono);
         let name = mono
             .get_common_name()
@@ -404,6 +432,10 @@
         &self.name
     }
 
+    fn type_param_names(&self) -> Vec<String> {
+        self.ty_params.clone().into_iter().map(|(ty, _)| ty).collect()
+    }
+
     /// Take some type arguments and produce a monomorphized version of the procedure.
     /// This monomorphized version can then be compiled directly. Additionally, the
     /// mono version of the procedure is memoized, so that it is only compiled once.
@@ -419,7 +451,7 @@
             .into_iter()
             .map(|ty| {
                 // Simplify the type until it is concrete
-                let concrete = ty.simplify_until_concrete(env)?;
+                let concrete = ty.simplify_until_concrete(env, true)?;
                 // concrete.add_monomorphized_associated_consts(env)?;
                 Ok(concrete)
             })
@@ -436,7 +468,7 @@
             );
             // Simplify the type until it is simple.
             // This reduces to the concrete version of the type application.
-            let concrete = ty.simplify_until_concrete(env)?;
+            let concrete = ty.simplify_until_concrete(env, true)?;
             // concrete.add_monomorphized_associated_consts(env)?;
             Ok(concrete)
         };
@@ -465,30 +497,29 @@
         drop(monomorphs);
         let mut monomorphs = self.monomorphs.write().unwrap();
 
+        debug!(target: "mono", "Memoizing monomorphized procedure {}", mangled_name);
+        let mut body = *self.body.clone();
+
+        // Substitute the type arguments into the body of the function.
+        body.substitute_types(&self.type_param_names(), &simplified_ty_args);
+
+        // Wrap the body in a let expression to bind the type arguments.
+        body = body.with(
+            self.type_param_names()
+                .iter()
+                .zip(simplified_ty_args.iter())
+                .map(|(a, b)| (a.clone(), b.clone()))
+                .collect::<Vec<_>>(),
+        );
+
+        let monomorph = Procedure::new(Some(mangled_name.clone()), args, ret, body);
+
         // If the monomorphized procedure has already been memoized, return it, otherwise memoize it.
         debug!(target: "mono", "Inserting entry for {}", mangled_name);
         let monomorph = monomorphs
             .entry(mangled_name.clone())
-            .or_insert_with(|| {
-                debug!(target: "mono", "Memoizing monomorphized procedure {}", mangled_name);
-                let mut body = *self.body.clone();
-
-                // Substitute the type arguments into the body of the function.
-                body.substitute_types(&self.ty_params, &simplified_ty_args);
-
-                // Wrap the body in a let expression to bind the type arguments.
-                body = body.with(
-                    self.ty_params
-                        .iter()
-                        .zip(simplified_ty_args.iter())
-                        .map(|(a, b)| (a.clone(), b.clone()))
-                        .collect::<Vec<_>>(),
-                );
-
-                Procedure::new(Some(mangled_name.clone()), args, ret, body)
-            })
+            .or_insert_with(|| monomorph)
             .clone();
-
         // Unlock the mutex to prevent a deadlock.
         drop(monomorphs);
         // Return the monomorphized procedure.
@@ -508,13 +539,19 @@
     }
 
     fn substitute(&mut self, name: &str, ty: &Type) {
-        if self.ty_params.contains(&name.to_string()) {
+        if self.type_param_names().contains(&name.to_string()) {
+            debug!("Not substituting {name} in {ty} because of symbol conflict");
             return;
         }
+        for (_, ty_arg) in &mut self.ty_params {
+            *ty_arg = ty_arg.as_mut().map(|ty_arg| ty_arg.substitute(name, ty));
+        }
+
         self.args
             .iter_mut()
             .for_each(|(_, _, t)| *t = t.substitute(name, ty));
         self.ret = self.ret.substitute(name, ty);
+        self.body.substitute(name, ty);
     }
 }
 
@@ -525,19 +562,24 @@
         }
 
         *self.has_type_checked.write().unwrap() = true;
-        trace!("Type checking {self}");
+        debug!("Type checking {self}");
         // Create a new scope for the procedure's body, and define the arguments for the scope.
         let mut new_env = env.new_scope();
+        
         // Define the type parameters of the procedure.
-        new_env.define_types(
-            self.ty_params
-                .clone()
-                .into_iter()
-                .map(|ty_param| (ty_param.clone(), Type::Unit(ty_param, Box::new(Type::None))))
-                .collect(),
-        );
+        for (name, ty) in &self.ty_params {
+            match ty {
+                Some(ty) => {
+                    new_env.define_var(name, Mutability::Immutable, ty.clone(), false)?;
+                    new_env.define_type(name, ty.clone());
+                }
+                None => {
+                    new_env.define_type(name, Type::Unit(name.clone(), Box::new(Type::None)));
+                }
+            }
+        }
         // Define the arguments of the procedure.
-        new_env.define_args(self.args.clone())?;
+        new_env.define_args(self.args.clone(), false)?;
         new_env.set_expected_return_type(self.ret.clone());
 
         // Typecheck the types of the arguments and return value
@@ -547,7 +589,9 @@
         self.ret.type_check(&new_env)?;
 
         // Get the type of the procedure's body, and confirm that it matches the return type.
-        let body_type = self.body.get_type(&new_env)?;
+        debug!("Getting body type of {}", self.name);
+        let body_type = self.body.get_type(&new_env)?;
+        debug!("Got body type {body_type} of {}", self.name);
 
         if !body_type.can_decay_to(&self.ret, &new_env)? {
             error!(
@@ -562,7 +606,8 @@
             })
         } else {
             // Typecheck the procedure's body.
-            self.body.type_check(&new_env)
+            debug!("Typechecking body of {} = {}", self.name, self.body);
+            self.body.type_check(&new_env)
         }
     }
 }
@@ -570,8 +615,11 @@
 impl fmt::Display for PolyProcedure {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "proc[")?;
-        for (i, ty_param) in self.ty_params.iter().enumerate() {
+        for (i, (ty_param, ty)) in self.ty_params.iter().enumerate() {
             write!(f, "{}", ty_param)?;
+            if let Some(ty) = ty {
+                write!(f, ": {}", ty)?;
+            }
             if i < self.ty_params.len() - 1 {
                 write!(f, ", ")?;
             }
diff --git a/docs/src/sage/lir/types/check.rs.html b/docs/src/sage/lir/types/check.rs.html
index 7de141bd..f83a544e 100644
--- a/docs/src/sage/lir/types/check.rs.html
+++ b/docs/src/sage/lir/types/check.rs.html
@@ -1318,6 +1318,24 @@
 1317
 1318
 1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
 
//! # Type Checking
 //!
 //! This module contains the type checking logic for the Lower Intermediate Representation.
@@ -1360,6 +1378,7 @@
             | Self::Char
             | Self::Enum(_) => Ok(()),
 
+            Self::ConstParam(cexpr) => cexpr.type_check(env),
             Self::Type(t) => t.type_check(env),
 
             // Units are sound if their inner type is sound.
@@ -1367,7 +1386,7 @@
 
             // Symbols are sound if they are defined in the environment
             Self::Symbol(name) => {
-                if env.get_type(name).is_some() {
+                if env.get_type(name).is_some() || env.get_const(name).is_some() {
                     Ok(())
                 } else {
                     debug!("Type {name} not defined in environment {env}");
@@ -1389,11 +1408,16 @@
                 // Check the inner type and the length constant-expression.
                 t.type_check(env)?;
                 len.clone().type_check(env)?;
+
                 // Check that the length is non-negative.
-                if len.clone().as_int(env)? < 0 {
-                    // If it is negative, return an error.
-                    error!("Negative array length detected in type {self} in environment {env}");
-                    return Err(Error::NegativeArrayLength(Expr::ConstExpr(*len.clone())));
+                debug!("About to convert {len} to int");
+                match len.clone().as_int(env) {
+                    Ok(n) if n < 0 => {
+                        // If it is negative, return an error.
+                        error!("Negative array length detected in type {self} in environment {env}");
+                        return Err(Error::NegativeArrayLength(Expr::ConstExpr(*len.clone())));
+                    }
+                    _ => {}
                 }
                 // Otherwise, return success.
                 Ok(())
@@ -1449,7 +1473,7 @@
                     ty_params
                         .clone()
                         .into_iter()
-                        .map(|p| (p.clone(), Type::Unit(p, Box::new(Type::Any))))
+                        .map(|p| (p.0.clone(), Type::Unit(p.0, Box::new(Type::Any))))
                         .collect(),
                 );
                 // Check the template type.
@@ -1472,14 +1496,14 @@
                     .try_for_each(|t| t.type_check(env))?;
 
                 // Try to confirm that the polymorphic type is a template.
-                match poly.simplify_until_poly(env)? {
+                match poly.simplify_until_poly(env, true)? {
                     Type::Symbol(name) => {
                         // Get the type definition.
                         let ty = env
                             .get_type(&name)
                             .ok_or(Error::TypeNotDefined(name.clone()))?;
                         // Check that the type is a template.
-                        match ty.simplify_until_poly(env)? {
+                        match ty.simplify_until_poly(env, true)? {
                             Type::Poly(ty_params, _) => {
                                 // Check that the number of type arguments matches the number of type parameters.
                                 if ty_args.len() != ty_params.len() {
@@ -1535,7 +1559,7 @@
                 // Check the declaration.
                 declaration.type_check(&new_env)?;
                 // Add the declarations to the environment.
-                new_env.add_declaration(declaration)?;
+                new_env.add_declaration(declaration, false)?;
                 // Check the body with the declarations defined.
                 body.type_check(&new_env)
             }
@@ -1632,7 +1656,7 @@
                     let bindings = pat.get_bindings(expr, &ty, env)?;
                     // Define the bindings in the environment.
                     for (name, (mutability, ty)) in bindings {
-                        new_env.define_var(name, mutability, ty)?;
+                        new_env.define_var(name, mutability, ty, false)?;
                     }
                     // Check the branch under the new environment.
                     pat.type_check(expr, branch, env)?;
@@ -1805,7 +1829,7 @@
                         Err(Error::InvalidRefer(self.clone()))
                     }
                 }
-                Expr::ConstExpr(_cexpr) => Ok(()),
+                Expr::ConstExpr(cexpr) => cexpr.type_check(env),
                 Expr::Deref(inner) | Expr::Index(inner, _) => {
                     // Confirm that the inner expression can be referenced.
                     match inner.get_type(env)? {
@@ -1828,7 +1852,9 @@
                             inner.refer(*expected_mutability).type_check(env)?;
                         }
 
-                        _ => {}
+                        ty => {
+                            warn!("Unexpected deref of type {ty}");
+                        }
                     }
 
                     e.type_check(env)
@@ -1894,7 +1920,7 @@
                 let ptr_type = ptr.get_type(env)?;
                 let val_type = val.get_type(env)?;
                 // Check that the pointer is a pointer.
-                if let Type::Pointer(mutability, ptr_elem_ty) = ptr_type {
+                if let Type::Pointer(mutability, ptr_elem_ty) = ptr_type.clone().discard_type_wrapper() {
                     // Check that the type of the value is compatible
                     // with the type of data stored at the pointer's
                     // address.
@@ -1945,7 +1971,7 @@
                         f.type_check(env)?;
 
                         // Get the type of the function.
-                        let f_type = f.get_type(env)?.simplify_until_concrete(env)?;
+                        let f_type = f.get_type(env)?.simplify_until_concrete(env, true)?;
                         // Infer the types of the supplied arguments.
                         let mut found_arg_tys = vec![];
                         for arg in args {
@@ -2000,7 +2026,7 @@
                 }
 
                 // Get the type of the function.
-                let f_type = f.get_type(env)?.simplify_until_concrete(env)?;
+                let f_type = f.get_type(env)?.simplify_until_concrete(env, true)?;
                 // Infer the types of the supplied arguments.
                 let mut found_arg_tys = vec![];
                 for arg in args {
@@ -2029,6 +2055,8 @@
                                     found,
                                     expr: self.clone(),
                                 });
+                            } else {
+                                debug!("Found {found} can decay to {expected} in {self}")
                             }
                         }
                         Ok(())
@@ -2052,9 +2080,9 @@
                 let expected = env
                     .get_expected_return_type()
                     .cloned()
-                    .unwrap_or(Type::None);
+                    .unwrap_or(Type::None).simplify(env)?;
                 if !found.can_decay_to(&expected, env)? {
-                    error!("The found return type does not match expected type");
+                    error!("The found return type {found} does not match expected type {expected} in {env}");
                     return Err(Error::MismatchedTypes {
                         expected,
                         found,
@@ -2103,7 +2131,7 @@
             Self::Union(t, field, val) => {
                 // Typecheck the type.
                 t.type_check(env)?;
-                let t = t.simplify_until_union(env)?;
+                let t = t.simplify_until_union(env, true)?;
                 match t {
                     Type::Union(fields) => {
                         // Confirm that the variant is a valid variant.
@@ -2137,7 +2165,7 @@
             Self::EnumUnion(t, variant, val) => {
                 // Typecheck the type
                 t.type_check(env)?;
-                let t = t.simplify_until_union(env)?;
+                let t = t.simplify_until_union(env, true)?;
 
                 match t {
                     Type::EnumUnion(fields) => {
@@ -2196,7 +2224,7 @@
                 match e_type.type_check_member(field, e, env) {
                     Ok(_) => Ok(()),
                     Err(e) => {
-                        warn!("Type {e_type} doesn't have member {field} in environment {env}");
+                        debug!("Type {e_type} doesn't have member {field} in environment {env}");
                         match field
                             .clone()
                             .as_symbol(env)
@@ -2245,26 +2273,26 @@
 // Typecheck a constant expression.
 impl TypeCheck for ConstExpr {
     fn type_check(&self, env: &Env) -> Result<(), Error> {
+        debug!("Typechecking constant expression: {}", self);
         if env.has_type_checked_const(self) {
             return Ok(());
         }
 
-        debug!("Typechecking constant expression: {}", self);
         match self {
-            Self::Template(_ty_params, _template) => {
+            Self::Any => Ok(()),
+            Self::Template(ty_params, template) => {
                 // Create a new environment with the type parameters defined.
-                // let mut new_env = env.clone();
-                // // Define the type parameters in the environment.
-                // new_env.define_types(
-                //     ty_params
-                //         .clone()
-                //         .into_iter()
-                //         .map(|p| (p.clone(), Type::Unit(p, Box::new(Type::None))))
-                //         .collect(),
-                // );
-                // Check the template type.
-                // template.type_check(&new_env)
-                Ok(())
+                let mut new_env = env.clone();
+                for (name, ty) in ty_params {
+                    if let Some(ty) = ty {
+                        new_env.define_type(name, ty.clone());
+                        new_env.define_var(name, Mutability::Immutable, ty.clone(), false)?;
+                    } else {
+                        new_env.define_type(name, Type::Unit(name.clone(), Box::new(Type::None)))
+                    }
+                }
+                // Check the template type.
+                template.type_check(&new_env)
             }
 
             Self::Annotated(expr, metadata) => expr
@@ -2280,26 +2308,25 @@
                 e.type_check(env)?;
                 // Get the type of the expression.
                 let e_type = e.get_type(env)?;
-                // e_type.add_monomorphized_associated_consts(env)?;
-                // Typecheck the member we want to access.
+                // Typecheck the member we want to access.
                 match e_type.type_check_member(field, &Expr::ConstExpr(*e.clone()), env) {
                     Ok(_) => Ok(()),
                     Err(_err) => {
-                        warn!("Member {field} not found in type {e_type} in environment {env}");
+                        debug!("Member {field} not found in type {e_type} in environment {env}");
                         match field
                             .clone()
                             .as_symbol(env)
                             .map(|name| env.get_associated_const(&e_type, &name))
                         {
                             Ok(_) => {
-                                warn!("Associated constant {field} found in type {e_type} in environment {env}");
+                                debug!("Associated constant {field} found in type {e_type} in environment {env}");
                                 Ok(())
                             }
                             // Err(_) => Err(e),
                             Err(_) => {
                                 // Try to perform the member op as a regular member op.
-                                warn!("Associated constant {field} not found in type {e_type} in environment {env}");
-                                warn!("Falling back on regular member access");
+                                debug!("Associated constant {field} not found in type {e_type} in environment {env}");
+                                debug!("Falling back on regular member access");
                                 Expr::Member(Box::new(Expr::ConstExpr(*e.clone())), *field.clone())
                                     .type_check(env)
                             }
@@ -2340,46 +2367,55 @@
                 debug!(
                     "Monomorphizing {expr} with type arguments {ty_args:?} in environment {env}"
                 );
-                match **expr {
+                match *expr.clone() {
                     Self::Template(ref ty_params, ref template) => {
+                        // Create a new environment with the type parameters defined.
+                        // Define the type parameters in the environment.
+                        let mut ret = template.clone();
+                        let mut new_env = env.clone();
+                        for ((param, ty), ty_arg) in ty_params.iter().zip(ty_args.iter()) {
+                            if ty_arg.is_const_param() {
+                                let cexpr = ty_arg.simplify_until_const_param(env, true)?;
+                                if let Some(expected_ty) = ty {
+                                    let expected = expected_ty.clone();
+                                    let found = cexpr.get_type(env)?;
+                                    if !found.equals(expected_ty, env)? {
+                                        error!("Mismatch in expected type for constant parameter");
+                                        return Err(Error::MismatchedTypes { expected, found, expr: (cexpr.clone()).into() })
+                                    }
+                                }
+                                ret.substitute(param, ty_arg);
+                                new_env.define_const(param, cexpr.clone());
+                            } else {
+                                ret.substitute(param, ty_arg);
+                                new_env.define_type(param, ty_arg.clone());
+                            }
+                        }
+                        debug!("Result: {ret}");
+                        let ret = ret.get_type(&new_env)?
+                            .simplify_until_poly(&new_env, true)?;
+                        // Check the template type.
+                        ret.type_check(&new_env)
+                    }
+                    Self::PolyProc(ref poly) => {
                         // Create a new environment with the type parameters defined.
                         let mut new_env = env.clone();
                         // Define the type parameters in the environment.
                         new_env.define_types(
-                            ty_params.clone().into_iter().zip(ty_args.clone()).collect(),
+                            poly.get_type_params()
+                                .clone()
+                                .into_iter()
+                                .map(|(name, _)| name)
+                                .zip(ty_args.clone())
+                                .collect(),
                         );
                         // Check the template type.
-                        template.type_check(&new_env)
-                        // Ok(())
-                    }
-                    Self::PolyProc(ref poly) => {
-                        // poly.monomorphize(ty_args.clone(), env)?.type_check(env)
-                        // Create a new environment with the type parameters defined.
-                        // let mut new_env = env.clone();
-                        // // Define the type parameters in the environment.
-                        // new_env.define_types(
-                        //     poly.ty_params
-                        //         .clone()
-                        //         .into_iter()
-                        //         .zip(ty_args.clone())
-                        //         .collect(),
-                        // );
-                        // Check the template type.
                         poly.type_check(env)
-                        // Ok(())
-                    }
+                    }
                     _ => {
                         self.get_type(env)?.type_check(env)?;
                         expr.type_check(env)?;
-                        // if let Self::PolyProc(poly) = *expr.clone() {
-                        //     poly.type_check(env)?
-                        // }
-                        /*
-                        for ty in ty_args {
-                            ty.type_check(env)?;
-                        }
-                        */
-                        ty_args
+                        ty_args
                             .into_par_iter()
                             .try_for_each(|ty| ty.type_check(env))?;
                         Ok(())
@@ -2441,7 +2477,7 @@
             // Typecheck a variant of an enum.
             Self::Of(t, variant) => {
                 let t = t
-                    .simplify_until_has_variants(env)
+                    .simplify_until_has_variants(env, true)
                     .map_err(|_| Error::VariantNotFound(t.clone(), variant.clone()))?;
 
                 match t {
@@ -2563,7 +2599,7 @@
             // Typecheck a union literal.
             Self::Union(t, field, val) => {
                 // Confirm the type supplied is a union.
-                let t = t.simplify_until_union(env)?;
+                let t = t.simplify_until_union(env, true)?;
 
                 match t {
                     Type::Union(fields) => {
@@ -2602,7 +2638,7 @@
             // Typecheck a tagged union literal.
             Self::EnumUnion(t, variant, val) => {
                 // Confirm the type supplied is a union.
-                let t = t.simplify_until_union(env)?;
+                let t = t.simplify_until_union(env, true)?;
                 match t {
                     Type::EnumUnion(fields) => {
                         // Confirm that the variant is a valid variant.
diff --git a/docs/src/sage/lir/types/inference.rs.html b/docs/src/sage/lir/types/inference.rs.html
index 795ece03..d38e29d5 100644
--- a/docs/src/sage/lir/types/inference.rs.html
+++ b/docs/src/sage/lir/types/inference.rs.html
@@ -557,8 +557,6 @@
 556
 557
 558
-559
-560
 
//! # Type Inference
 //!
 //! This module contains the type inference algorithm for the language.
@@ -618,7 +616,7 @@
                 // Create a new environment with the declarations.
                 let mut new_env = env.clone();
                 // Add the declarations to the environment.
-                new_env.add_declaration(declaration)?;
+                new_env.add_declaration(declaration, false)?;
                 // Get the type of the body in the new environment.
                 body.get_type_checked(&new_env, i)?
             }
@@ -793,7 +791,7 @@
                 // Get the type of the expression.
                 let t = expr
                     .get_type_checked(env, i)?
-                    .simplify_until_concrete(env)?;
+                    .simplify_until_concrete(env, false)?;
                 // If the type is a pointer, return the inner type of the pointer.
                 if let Type::Pointer(_, inner) = t {
                     // If the type *evaluates* to a pointer, return that inner type.
@@ -814,7 +812,7 @@
                 // Get the type of the function.
                 let ty = func
                     .get_type_checked(env, i)?
-                    .simplify_until_concrete(env)?;
+                    .simplify_until_concrete(env, false)?;
                 match ty {
                     Type::Proc(_, ret) => *ret,
                     _ => return Err(Error::ApplyNonProc(self.clone())),
@@ -874,13 +872,11 @@
                 // Get the type of the value to get the member of.
                 let val_type = val.get_type_checked(env, i)?;
                 // val_type.add_monomorphized_associated_consts(env)?;
-                let val_type = val_type.simplify_until_concrete(env)?;
+                let val_type = val_type.simplify_until_concrete(env, false)?;
                 // val_type.add_monomorphized_associated_consts(env)?;
                 match val_type {
                     Type::Type(ty) => {
-                        // ty.add_monomorphized_associated_consts(env)?;
-
-                        // Get the associated constant expression's type.
+                        // Get the associated constant expression's type.
                         env.get_type_of_associated_const(&ty, &as_symbol?)
                             .ok_or(Error::MemberNotFound(*val.clone(), field.clone()))?
                     }
diff --git a/docs/src/sage/lir/types/mod.rs.html b/docs/src/sage/lir/types/mod.rs.html
index 92ea5ee6..b2eda34c 100644
--- a/docs/src/sage/lir/types/mod.rs.html
+++ b/docs/src/sage/lir/types/mod.rs.html
@@ -2359,6 +2359,235 @@
 2358
 2359
 2360
+2361
+2362
+2363
+2364
+2365
+2366
+2367
+2368
+2369
+2370
+2371
+2372
+2373
+2374
+2375
+2376
+2377
+2378
+2379
+2380
+2381
+2382
+2383
+2384
+2385
+2386
+2387
+2388
+2389
+2390
+2391
+2392
+2393
+2394
+2395
+2396
+2397
+2398
+2399
+2400
+2401
+2402
+2403
+2404
+2405
+2406
+2407
+2408
+2409
+2410
+2411
+2412
+2413
+2414
+2415
+2416
+2417
+2418
+2419
+2420
+2421
+2422
+2423
+2424
+2425
+2426
+2427
+2428
+2429
+2430
+2431
+2432
+2433
+2434
+2435
+2436
+2437
+2438
+2439
+2440
+2441
+2442
+2443
+2444
+2445
+2446
+2447
+2448
+2449
+2450
+2451
+2452
+2453
+2454
+2455
+2456
+2457
+2458
+2459
+2460
+2461
+2462
+2463
+2464
+2465
+2466
+2467
+2468
+2469
+2470
+2471
+2472
+2473
+2474
+2475
+2476
+2477
+2478
+2479
+2480
+2481
+2482
+2483
+2484
+2485
+2486
+2487
+2488
+2489
+2490
+2491
+2492
+2493
+2494
+2495
+2496
+2497
+2498
+2499
+2500
+2501
+2502
+2503
+2504
+2505
+2506
+2507
+2508
+2509
+2510
+2511
+2512
+2513
+2514
+2515
+2516
+2517
+2518
+2519
+2520
+2521
+2522
+2523
+2524
+2525
+2526
+2527
+2528
+2529
+2530
+2531
+2532
+2533
+2534
+2535
+2536
+2537
+2538
+2539
+2540
+2541
+2542
+2543
+2544
+2545
+2546
+2547
+2548
+2549
+2550
+2551
+2552
+2553
+2554
+2555
+2556
+2557
+2558
+2559
+2560
+2561
+2562
+2563
+2564
+2565
+2566
+2567
+2568
+2569
+2570
+2571
+2572
+2573
+2574
+2575
+2576
+2577
+2578
+2579
+2580
+2581
+2582
+2583
+2584
+2585
+2586
+2587
+2588
+2589
 
//! # Types Module
 //!
 //! This module contains a collection of types and traits
@@ -2552,11 +2781,15 @@
     /// The type takes a list of symbols that are substituted with concrete types.
     /// The type is then simplified to a concrete type when combined with `Apply`.
     /// This type is used to implement generics.
-    Poly(Vec<String>, Box<Self>),
+    Poly(Vec<(String, Option<Type>)>, Box<Self>),
 
     /// A type that constructs a concrete type from a polymorphic type.
     /// This type is used to implement generics.
     Apply(Box<Self>, Vec<Self>),
+
+    /// A constant literal used in a type expression, like a template application
+    /// with a constant parameter.
+    ConstParam(Box<ConstExpr>),
 }
 
 lazy_static::lazy_static! {
@@ -2577,7 +2810,29 @@
         self.is_recursive_helper(&mut symbols, env)
     }
 
-    pub fn is_recursive_helper(
+    /// Is this type a constant parameter?
+    /// 
+    /// This will recursively detect if the subtypes are constant parameters as well
+    pub fn is_const_param(&self) -> bool {
+        match self {
+            Type::ConstParam(..) => true,
+            Type::Struct(fields) => fields.iter().map(|(_name, ty)| ty).all(Self::is_const_param),
+            Type::Tuple(items) => items.iter().all(Self::is_const_param),
+            Type::Type(t) => t.is_const_param(),
+            _ => false,
+        }
+    }
+
+    /// Discard the wrappers of Type::Type and Type::Unit
+    pub(crate) fn discard_type_wrapper(self) -> Self {
+        match self {
+            Self::Type(ty) | Self::Unit(_, ty) => *ty,
+            other => other
+        }
+    }
+
+    /// Is this type recursive?
+    pub fn is_recursive_helper(
         &self,
         symbols: &mut HashSet<String>,
         env: &Env,
@@ -2626,7 +2881,7 @@
             }
 
             Self::Poly(params, t) => {
-                for param in params {
+                for (param, _) in params {
                     symbols.remove(param);
                 }
                 t.is_recursive_helper(symbols, env)
@@ -2678,7 +2933,9 @@
                 Ok(false)
             }
             Self::Enum(_) => Ok(false),
-            Self::None
+
+            Self::ConstParam(_)
+            | Self::None
             | Self::Int
             | Self::Float
             | Self::Cell
@@ -2701,7 +2958,8 @@
         result
     }
 
-    pub fn strip_template(&self, env: &Env) -> Self {
+    /// Strip the template arguments to get the inner type
+    pub fn strip_template(&self, env: &Env) -> Self {
         debug!("strip_template: {}", self);
         match self {
             Self::Apply(template, _) => template.strip_template(env),
@@ -2714,18 +2972,22 @@
                     self.clone()
                 }
             }
+            Self::Pointer(mutability, ty) => Self::Pointer(*mutability, ty.strip_template(env).into()),
             _ => self.clone(),
         }
     }
 
-    pub fn is_poly(&self) -> bool {
+    /// Is this a polymorphic function?
+    pub fn is_poly(&self) -> bool {
         matches!(self, Self::Poly(_, _))
     }
 
-    pub fn get_monomorph_template_args(
+    /// Get the template arguments for the monomorph (this type) of some polymorphic base type.
+    /// This will match the symbols in the template against the monomorph.
+    pub fn get_monomorph_template_args(
         &self,
         template: &Self,
-        matched_symbols: &mut HashMap<String, Self>,
+        matched_symbols: &mut HashMap<String, (Self, Option<Type>)>,
         param_symbols: &HashSet<String>,
         env: &Env,
     ) -> Result<(), Error> {
@@ -2783,9 +3045,22 @@
                 }
             }
 
-            (Self::Array(inner1, _), Self::Array(inner2, _)) => {
+            (Self::Array(inner1, cexpr1), Self::Array(inner2, cexpr2)) => {
                 inner1.get_monomorph_template_args(inner2, matched_symbols, param_symbols, env)?;
-            }
+
+                let ty1 = match &**cexpr1 {
+                    ConstExpr::Symbol(name) => Type::Symbol(name.clone()),
+                    ConstExpr::Type(ty) => ty.clone(),
+                    otherwise => Type::ConstParam(otherwise.clone().into())
+                };
+                let ty2 = match &**cexpr2 {
+                    ConstExpr::Symbol(name) => Type::Symbol(name.clone()),
+                    ConstExpr::Type(ty) => ty.clone(),
+                    _ => return Ok(())
+                };
+
+                ty1.get_monomorph_template_args(&ty2, matched_symbols, param_symbols, env)?
+            }
 
             (Self::Pointer(_, inner1), Self::Pointer(_, inner2)) => {
                 inner1.get_monomorph_template_args(inner2, matched_symbols, param_symbols, env)?;
@@ -2815,18 +3090,18 @@
             }
 
             (Self::Apply(template, args), Self::Poly(params, ret)) => {
-                for (param, arg) in params.iter().zip(args.iter()) {
+                for ((param, expected), arg) in params.iter().zip(args.iter()) {
                     // ret.get_monomorph_template_args(arg, symbols, env)?;
-                    matched_symbols.insert(param.clone(), arg.clone());
+                    matched_symbols.insert(param.clone(), (arg.clone(), expected.clone()));
                     debug!("Found match {}: {}", param, arg);
                 }
                 template.get_monomorph_template_args(ret, matched_symbols, param_symbols, env)?;
             }
 
             (Self::Apply(template, args), other) => {
-                if let Ok(Self::Poly(params, ret)) = template.simplify_until_poly(env) {
+                if let Ok(Self::Poly(params, ret)) = template.simplify_until_poly(env, false) {
                     let mut ret = *ret.clone();
-                    for (param, arg) in params.iter().zip(args.iter()) {
+                    for ((param, _), arg) in params.iter().zip(args.iter()) {
                         ret = ret.substitute(param, arg);
                     }
 
@@ -2836,7 +3111,7 @@
             (other, Self::Symbol(name)) => {
                 if param_symbols.contains(name) {
                     debug!("Found match {}: {}", name, other);
-                    matched_symbols.insert(name.clone(), other.clone());
+                    matched_symbols.insert(name.clone(), (other.clone(), None));
                 } else if let Some(t) = env.get_type(name) {
                     debug!("Symbol {name} is {t}");
                     other.get_monomorph_template_args(t, matched_symbols, param_symbols, env)?;
@@ -2851,7 +3126,7 @@
 
             (a, b) => {
                 if a != b {
-                    error!(
+                    debug!(
                         "get_monomorph_template_args: Couldn't match {} to {}",
                         self, template
                     );
@@ -2862,12 +3137,16 @@
         Ok(())
     }
 
-    pub fn is_monomorph_of(&self, template: &Self, env: &Env) -> Result<bool, Error> {
-        match (self, template) {
-            (Self::Apply(template1, _), template2) => template1.equals(template2, env),
+    /// Is this type a monomorph of a given template type?
+    pub fn is_monomorph_of(&self, template: &Self, env: &Env) -> Result<bool, Error> {
+        debug!("{self} is mono of {template}?");
+        let result = match (self, template) {
+            (Self::Apply(template1, _), template2) => {
+                template1.equals(template2, env)
+            },
             (concrete, Self::Poly(params, result)) => {
                 let mut result = *result.clone();
-                for param in params {
+                for (param, _) in params {
                     result = result.substitute(param, &Type::Any);
                 }
                 concrete.equals(&result, env)
@@ -2886,24 +3165,39 @@
                 Ok(false)
             }
 
+            (Self::Pointer(mut1, ty1), Self::Pointer(mut2, ty2)) => {
+                Ok(mut1 == mut2 && ty1.is_monomorph_of(ty2, env)?)
+            }
+
+            (Self::Array(elem1, len1), Self::Array(elem2, len2)) => {
+                return Ok(elem1.is_monomorph_of(elem2, env)? && len1.get_type(env)?.equals(&len2.get_type(env)?, env)?)
+            }
+
+            (Self::ConstParam(cexpr), other) => cexpr.get_type(env)?.equals(other, env),
+
             _ => Ok(false),
+        };
+        if result.clone().is_ok_and(|x| x) {
+            debug!("{self} is monomorph of {template}");
+        } else {
+            debug!("{self} is NOT monomorph of {template}");
         }
+        result
     }
 
-    pub fn add_monomorphized_associated_consts(&self, env: &Env) -> Result<(), Error> {
-        // warn!("add_monomorphized_associated_consts: Adding monomorphized associated consts for {}", self);
-        match self.clone() {
+    /// Add monomorphized methods for a given monomorph of a template type with methods.
+    pub fn add_monomorphized_associated_consts(&self, env: &Env) -> Result<(), Error> {
+        match self.clone() {
             Self::Apply(template, args) => {
                 let simplified_args = args
                     .iter()
-                    .map(|t| t.simplify_until_concrete(env))
+                    .map(|t| t.simplify_until_concrete(env, false))
                     .collect::<Result<Vec<_>, _>>()?;
 
                 let mut mono_ty = Self::Apply(template.clone(), simplified_args.clone());
-                mono_ty = mono_ty.simplify_until_concrete(env)?;
-                // warn!("add_monomorphized_associated_consts: Adding monomorphized associated consts for {self} to {}", mono_ty);
+                mono_ty = mono_ty.simplify_until_concrete(env, false)?;
 
-                env.add_monomorphized_associated_consts(*template, mono_ty, simplified_args)?;
+                env.add_monomorphized_associated_consts(*template, mono_ty, simplified_args)?;
             }
 
             Self::Struct(fields) => {
@@ -2954,6 +3248,7 @@
                 // t.add_monomorphized_associated_consts(env)?;
             }
             Self::Let(_, _, _)
+            | Self::ConstParam(_)
             | Self::Any
             | Self::None
             | Self::Never
@@ -2967,26 +3262,16 @@
         Ok(())
     }
 
-    pub fn get_template_params(&self, env: &Env) -> Vec<String> {
+    /// Get the template parameters for this template type.
+    pub fn get_template_params(&self, env: &Env) -> Vec<(String, Option<Type>)> {
         debug!("get_template_params: {}", self);
-        match self.simplify_until_poly(env) {
+        match self.simplify_until_poly(env, false) {
             Ok(Self::Poly(params, _)) => {
-                debug!(
-                    "get_template_params: {} params: {}",
-                    self,
-                    params.join(", ")
-                );
                 params.clone()
             }
             Ok(Self::Symbol(name)) => {
                 if let Some(t) = env.get_type(&name) {
-                    let result = t.get_template_params(env);
-                    debug!(
-                        "get_template_params: {} params: {}",
-                        name,
-                        result.join(", ")
-                    );
-                    result
+                    t.get_template_params(env)
                 } else {
                     debug!("get_template_params: Couldn't find type {}", name);
                     vec![]
@@ -3002,7 +3287,8 @@
         }
     }
 
-    pub fn apply(&self, args: Vec<Self>) -> Self {
+    /// Apply this template type with some type arguments.
+    pub fn apply(&self, args: Vec<Self>) -> Self {
         Self::Apply(Box::new(self.clone()), args)
     }
 
@@ -3024,6 +3310,7 @@
             | Self::Bool
             | Self::Any
             | Self::Never
+            | Self::ConstParam(_)
             | Self::Enum(_)
             | Self::Type(_) => true,
             Self::Unit(_, t) => t.is_simple(),
@@ -3043,7 +3330,7 @@
                         return false;
                     }
                     let mut ret = *ret.clone();
-                    for (param, arg) in params.iter().zip(args.iter()) {
+                    for ((param, _), arg) in params.iter().zip(args.iter()) {
                         if !arg.is_simple() {
                             return false;
                         }
@@ -3060,9 +3347,14 @@
         }
     }
 
-    pub fn is_concrete(&self) -> bool {
+    /// Is this type simplified enough to get information about what the
+    /// outer type is? Is it a tuple, a struct, etc?
+    /// 
+    /// Symbols and polymorphic types do not satisfy this condition.
+    pub fn is_concrete(&self) -> bool {
         match self {
             Self::Poly(_, _) | Self::Symbol(_) | Self::Apply(_, _) | Self::Let(_, _, _) => false,
+
             Self::None
             | Self::Int
             | Self::Float
@@ -3071,6 +3363,7 @@
             | Self::Bool
             | Self::Any
             | Self::Never
+            | Self::ConstParam(_)
             | Self::Enum(_)
             | Self::EnumUnion(_)
             | Self::Struct(_)
@@ -3078,8 +3371,8 @@
             | Self::Proc(_, _)
             | Self::Tuple(_)
             | Self::Unit(_, _)
-            | Self::Type(_)
             | Self::Array(_, _)
+            | Self::Type(_)
             | Self::Pointer(_, _) => true,
         }
     }
@@ -3096,7 +3389,9 @@
             | Self::Any
             | Self::Never
             | Self::Enum(_)
+            | Self::ConstParam(_)
             | Self::Type(_) => true,
+            
             Self::Unit(_, t) => t.is_atomic(),
             Self::Tuple(inner) => inner.iter().all(|t| t.is_atomic()),
             Self::Array(inner, expr) => inner.is_atomic() && matches!(**expr, ConstExpr::Int(_)),
@@ -3104,15 +3399,14 @@
             Self::Pointer(_, inner) => inner.is_atomic(),
             Self::Struct(inner) => inner.iter().all(|(_, t)| t.is_atomic()),
             Self::EnumUnion(inner) => inner.iter().all(|(_, t)| t.is_atomic()),
-            // Self::Poly(_, _) | Self::Symbol(_) | Self::Apply(_, _) => false,
-            // Self::Let(_, _, ret) => ret.is_atomic(),
-            _ => false,
+
+            _ => false,
         }
     }
 
     /// Is first argument of function a reference?
     pub fn is_self_param_reference(&self, env: &Env) -> Result<bool, Error> {
-        Ok(match self.simplify_until_concrete(env)? {
+        Ok(match self.simplify_until_concrete(env, false)? {
             Self::Proc(args, _) => {
                 matches!(args.first(), Some(Self::Pointer(_, _)))
             }
@@ -3122,7 +3416,7 @@
 
     /// Get the first argument's mutability (if it is a pointer)
     pub fn get_self_param_mutability(&self, env: &Env) -> Option<Mutability> {
-        match self.simplify_until_concrete(env) {
+        match self.simplify_until_concrete(env, false) {
             Ok(Self::Proc(args, _)) => {
                 if let Some(Self::Pointer(mutability, _)) = args.first() {
                     Some(*mutability)
@@ -3135,7 +3429,7 @@
             Ok(Self::Apply(template, args)) => {
                 if let Self::Poly(ref params, ref inner) = *template {
                     let mut inner = *inner.clone();
-                    for (param, arg) in params.iter().zip(args.iter()) {
+                    for ((param, _), arg) in params.iter().zip(args.iter()) {
                         inner = inner.substitute(param, arg);
                     }
                     inner.get_self_param_mutability(env)
@@ -3151,10 +3445,11 @@
     /// Simplify until the type passes the type checker.
     pub fn simplify_until_type_checks(&self, env: &Env) -> Result<Self, Error> {
         self.clone()
-            .simplify_until_matches(env, Type::Any, |t, env| t.type_check(env).map(|_| true))
+            .simplify_until_matches(env, Type::Any, |t, env| t.type_check(env).map(|_| true), true)
     }
 
-    fn possibly_has_members(&self) -> bool {
+    /// Does this type possibly have some members/fields?
+    fn possibly_has_members(&self) -> bool {
         if matches!(
             self,
             Self::Tuple(_) | Self::Struct(_) | Self::Union(_) | Self::Pointer(_, _) | Self::Type(_)
@@ -3170,10 +3465,10 @@
     }
 
     /// Simplify a type until you can get its members.
-    pub fn simplify_until_has_members(&self, env: &Env) -> Result<Self, Error> {
+    pub fn simplify_until_has_members(&self, env: &Env, checked: bool) -> Result<Self, Error> {
         let result = self
             .clone()
-            .simplify_until_matches(env, Type::Any, |t, _| Ok(t.possibly_has_members()));
+            .simplify_until_matches(env, Type::Any, |t, _| Ok(t.possibly_has_members()), checked);
 
         if result.is_err() {
             warn!("Couldn't simplify {} to a type with members", self);
@@ -3182,7 +3477,8 @@
         result
     }
 
-    fn is_union(&self) -> bool {
+    /// Is this a union type?
+    fn is_union(&self) -> bool {
         if matches!(self, Self::Union(_) | Self::EnumUnion(_)) {
             return true;
         }
@@ -3195,17 +3491,18 @@
     }
 
     /// Simplify a type until it's a union.
-    pub fn simplify_until_union(&self, env: &Env) -> Result<Self, Error> {
+    pub fn simplify_until_union(&self, env: &Env, checked: bool) -> Result<Self, Error> {
         let result = self
             .clone()
-            .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_union()));
+            .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_union()), checked);
         if result.is_err() {
             debug!("Couldn't simplify {} to a union", self);
         }
         result
     }
 
-    fn has_variants(&self) -> bool {
+    /// Does this type have enum variants?
+    fn has_variants(&self) -> bool {
         if matches!(self, Self::Enum(_) | Self::EnumUnion(_)) {
             return true;
         }
@@ -3218,17 +3515,18 @@
     }
 
     /// Simplify a type until you can get its variants.
-    pub fn simplify_until_has_variants(&self, env: &Env) -> Result<Self, Error> {
+    pub fn simplify_until_has_variants(&self, env: &Env, checked: bool) -> Result<Self, Error> {
         let result = self
             .clone()
-            .simplify_until_matches(env, Type::Enum(vec![]), |t, _| Ok(t.has_variants()));
+            .simplify_until_matches(env, Type::Enum(vec![]), |t, _| Ok(t.has_variants()), checked);
         if result.is_err() {
             debug!("Couldn't simplify {} to a type with variants", self);
         }
         result
     }
 
-    fn is_polymorphic(&self) -> bool {
+    /// Is this type polymorphic?
+    fn is_polymorphic(&self) -> bool {
         if matches!(self, Self::Poly(_, _)) {
             return true;
         }
@@ -3240,19 +3538,19 @@
         false
     }
 
-    pub fn simplify_until_atomic(&self, env: &Env) -> Result<Self, Error> {
+    pub fn simplify_until_atomic(&self, env: &Env, checked: bool) -> Result<Self, Error> {
         let result = self
             .clone()
-            .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_atomic()));
+            .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_atomic()), checked);
         if result.is_err() {
             debug!("Couldn't simplify {} to an atomic type", self);
         }
         result
     }
-    pub fn simplify_until_simple(&self, env: &Env) -> Result<Self, Error> {
+    pub fn simplify_until_simple(&self, env: &Env, checked: bool) -> Result<Self, Error> {
         let result = self
             .clone()
-            .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_simple()));
+            .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_simple()), checked);
         if result.is_err() {
             debug!("Couldn't simplify {} to a simple type", self);
         }
@@ -3260,11 +3558,12 @@
     }
 
     /// Simplify until the type is a polymorphic type.
-    pub fn simplify_until_poly(&self, env: &Env) -> Result<Self, Error> {
+    pub fn simplify_until_poly(&self, env: &Env, checked: bool) -> Result<Self, Error> {
         let result = self.clone().simplify_until_matches(
             env,
             Type::Poly(vec![], Box::new(Type::Any)),
             |t, _| Ok(t.is_polymorphic()),
+            checked
         );
         if result.is_err() {
             debug!("Couldn't simplify {} to a polymorphic type", self);
@@ -3273,16 +3572,75 @@
     }
 
     /// Simplify until the type is concrete.
-    pub fn simplify_until_concrete(&self, env: &Env) -> Result<Self, Error> {
+    pub fn simplify_until_concrete(&self, env: &Env, checked: bool) -> Result<Self, Error> {
         let result = self
             .clone()
-            .simplify_until_matches(env, Type::Any, |t, _env| Ok(t.is_concrete()));
+            .simplify_until_matches(env, Type::Any, |t, _env| Ok(t.is_concrete()), checked);
         if result.is_err() {
             debug!("Couldn't simplify {} to a concrete type", self);
         }
+        
         result
     }
 
+    /// Simplify until the type is concrete.
+    pub fn simplify_until_const_param(&self, env: &Env, _checked: bool) -> Result<ConstExpr, Error> {
+        let mut simplified = self.clone();
+        for _ in 0..3 {
+            if let Self::ConstParam(cexpr) = simplified {
+                return Ok(*cexpr);
+            }
+            simplified = simplified.simplify(env)?;
+            if let Self::ConstParam(cexpr) = simplified {
+                return Ok(*cexpr);
+            }
+            simplified = match simplified {
+                Self::Tuple(items) => {
+                    let simple_items = items
+                        .into_iter()
+                        .map(|t| t.simplify(env))
+                        .collect::<Result<Vec<_>, Error>>()?;
+                    
+                    if simple_items.iter().all(Self::is_const_param) {
+                        Self::ConstParam(ConstExpr::Tuple(simple_items
+                            .into_iter()
+                            .map(|t| Ok(match t {
+                                Type::ConstParam(cexpr) => cexpr.eval(env)?,
+                                _ => unreachable!()
+                            }))
+                            .collect::<Result<_, Error>>()?).into())
+                    } else {
+                        Self::Tuple(simple_items)
+                    }
+                }
+                Self::Struct(fields) => {
+                    let simple_fields = fields
+                        .into_iter()
+                        .map(|(name, t)| Ok((name, t.simplify(env)?)))
+                        .collect::<Result<BTreeMap<_, _>, Error>>()?;
+                    
+                    if simple_fields.iter().map(|(_x, t)| t).all(Self::is_const_param) {
+                        Self::ConstParam(ConstExpr::Struct(simple_fields
+                            .into_iter()
+                            .map(|(name, t)| Ok(match t {
+                                Type::ConstParam(cexpr) => (name, cexpr.eval(env)?),
+                                _ => unreachable!()
+                            }))
+                            .collect::<Result<_, Error>>()?).into())
+                    } else {
+                        Self::Struct(simple_fields)
+                    }
+                }
+                other => other
+            };
+        }
+
+        match simplified {
+            Type::ConstParam(cexpr) => Ok(*cexpr),
+            result => panic!("Unexpected {result}")
+        }
+    }
+
     /// Simplify an expression until it matches a given function which "approves" of a type.
     /// This will perform template applications to simplify the type if possible as well.
     ///
@@ -3293,6 +3651,7 @@
         env: &Env,
         expected: Self,
         f: impl Fn(&Self, &Env) -> Result<bool, Error>,
+        checked: bool
     ) -> Result<Self, Error> {
         let mut simplified = self;
         // for _ in 0..Self::SIMPLIFY_RECURSION_LIMIT {
@@ -3300,7 +3659,7 @@
             if f(&simplified, env)? || simplified.is_atomic() {
                 return Ok(simplified);
             }
-            simplified = simplified.perform_template_applications(env, &mut HashMap::new())?
+            simplified = simplified.perform_template_applications(env, &mut HashMap::new(), checked)?
         }
         Err(Error::CouldntSimplify(simplified, expected))
     }
@@ -3331,7 +3690,7 @@
             }
             Self::Type(t) => t.contains_symbol(name),
             Self::Poly(ty_params, template) => {
-                if ty_params.contains(&name.to_string()) {
+                if ty_params.iter().map(|x| x.0.clone()).collect::<Vec<_>>().contains(&name.to_string()) {
                     // This type variable is shadowed by a template variable.
                     false
                 } else {
@@ -3351,6 +3710,12 @@
                 t.contains_symbol(name) || (typename != name && ret.contains_symbol(name))
             }
             Self::Symbol(typename) => typename == name,
+            Self::ConstParam(cexpr) => {
+                match &**cexpr {
+                    ConstExpr::Symbol(const_name) | ConstExpr::Type(Type::Symbol(const_name)) => name == const_name,
+                    _ => false
+                }
+            }
             Self::None
             | Self::Never
             | Self::Any
@@ -3377,7 +3742,7 @@
     /// Substitute all occurences of a symbol with another type.
     /// This will not traverse into let-bindings when the symbol is overshadowed.
     pub fn substitute(&self, name: &str, substitution: &Self) -> Self {
-        match self {
+        let result = match self {
             Self::Type(t) => Self::Type(Box::new(t.substitute(name, substitution))),
             Self::Let(typename, binding, ret) => Self::Let(
                 typename.clone(),
@@ -3397,13 +3762,13 @@
                 },
             ),
             Self::Poly(ty_params, template) => {
-                if ty_params.contains(&name.to_string()) {
+                if ty_params.iter().map(|x| x.0.clone()).collect::<Vec<_>>().contains(&name.to_string()) {
                     // This type variable is shadowed by a template variable.
                     self.clone()
                 } else {
                     // Does the inner symbol use this type variable?
                     Self::Poly(
-                        ty_params.clone(),
+                        ty_params.iter().map(|(x, ty)| (x.clone(), ty.as_ref().map(|ty| ty.substitute(name, substitution)))).collect(),
                         template.substitute(name, substitution).into(),
                     )
                 }
@@ -3425,6 +3790,11 @@
                 unit_name.clone(),
                 Box::new(inner.substitute(name, substitution)),
             ),
+            Self::ConstParam(cexpr) => {
+                let mut cexpr = cexpr.clone();
+                cexpr.substitute(name, substitution);
+                Self::ConstParam(cexpr)
+            },
             Self::None
             | Self::Never
             | Self::Any
@@ -3440,10 +3810,14 @@
                     .map(|field_t| field_t.substitute(name, substitution))
                     .collect(),
             ),
-            Self::Array(item_t, size) => Self::Array(
-                Box::new(item_t.substitute(name, substitution)),
-                size.clone(),
-            ),
+            Self::Array(item_t, size) => {
+                let mut size = size.clone();
+                size.substitute(name, substitution);
+                Self::Array(
+                    Box::new(item_t.substitute(name, substitution)),
+                    size,
+                )
+            },
             Self::Struct(fields) => Self::Struct(
                 fields
                     .iter()
@@ -3477,7 +3851,8 @@
             Self::Pointer(mutability, ptr) => {
                 Self::Pointer(*mutability, Box::new(ptr.substitute(name, substitution)))
             }
-        }
+        };
+        result
     }
 
     /// Does this type have an element type matching the supplied type?
@@ -3500,18 +3875,13 @@
     /// For all cases right now, a decay does nothing; the representations of the types
     /// in the compiler are the same for all types of decay.
     pub fn can_decay_to(&self, desired: &Self, env: &Env) -> Result<bool, Error> {
-        trace!("Checking if {} can decay to {}", self, desired);
-        if self.equals(desired, env)? {
+        // trace!("Checking if {} can decay to {}", self, desired);
+        if self.equals(desired, env)? {
             return Ok(true);
         }
 
-        // if !self.is_simple() || !desired.is_simple() {
-        //     return Ok(false);
-        // }
-
-        match (self, desired) {
-            // (Self::Unit(_, inner), _) => inner.can_decay_to(desired, env),
-            (Self::Unit(name1, t1), Self::Unit(name2, t2)) => {
+        match (self, desired) {
+            (Self::Unit(name1, t1), Self::Unit(name2, t2)) => {
                 if name1 == name2 {
                     t1.can_decay_to(t2, env)
                 } else {
@@ -3554,6 +3924,8 @@
                     return Ok(true);
                 }
 
+                debug!("Could not decay {self} into {desired}");
+
                 Ok(false)
             }
 
@@ -3575,19 +3947,19 @@
             }
 
             // Can an array decay to another array?
-            (Self::Array(found_elem_ty, _), Self::Array(desired_elem_ty, _)) => {
+            (Self::Array(found_elem_ty, found_len), Self::Array(desired_elem_ty, expected_len)) => {
                 // Check if the element types can decay, and if the sizes are equal.
                 if found_elem_ty.can_decay_to(desired_elem_ty, env)?
-                    && self.get_size(env)? == desired.get_size(env)?
-                {
+                    && found_len.clone().eval(env)?.equals(&expected_len.clone().eval(env)?, env)
+                {
                     trace!("{} can decay to {}", self, desired);
                     return Ok(true);
                 }
 
                 // Check if the element types are compatible, and if the sizes are equal.
                 if found_elem_ty.has_element_type(desired_elem_ty, env)?
-                    && self.get_size(env)? == desired.get_size(env)?
-                {
+                    && found_len.clone().eval(env)?.equals(&expected_len.clone().eval(env)?, env)
+                {
                     trace!("{} can decay to {}", self, desired);
                     return Ok(true);
                 }
@@ -3619,24 +3991,7 @@
                 trace!("{} can decay to {}", self, desired);
                 Ok(true)
             }
-
-            // (Type::Apply(f, args), other) => {
-            //     match *f.clone() {
-            //         Type::Poly(params, template) => {
-            //             let mut template = *template.clone();
-            //             for (param, arg) in params.iter().zip(args.iter()) {
-            //                 template = template.substitute(param, arg);
-            //             }
-            //             template.can_decay_to(other, env)
-            //         }
-
-            //     }
-            //     // let mut f = f.clone();
-            //     // for arg in args {
-            //     //     f = f.substitute(, substitution)
-            //     // }
-            // }
-            (Type::Cell, Type::Int) | (Type::Int, Type::Cell) => Ok(true),
+            (Type::Cell, Type::Int) | (Type::Int, Type::Cell) => Ok(true),
 
             (a, b) => a.equals(b, env),
         }
@@ -3669,6 +4024,8 @@
         }
 
         let result = match (self, other) {
+            (Self::ConstParam(a), Self::ConstParam(b)) => Ok(a.equals(b, env)),
+
             (Self::Let(name, t, ret), other) | (other, Self::Let(name, t, ret)) => {
                 let mut new_env = env.clone();
                 new_env.define_type(name, *t.clone());
@@ -3790,6 +4147,7 @@
         &self,
         env: &Env,
         previous_applications: &mut HashMap<(Type, Vec<Type>), Type>,
+        checked: bool,
     ) -> Result<Self, Error> {
         let _before = self.to_string();
         trace!("Performing template applications on {}", self);
@@ -3800,10 +4158,10 @@
         Ok(match self.clone().simplify(env)? {
             Self::Apply(poly, ty_args) => {
                 let pair = (
-                    poly.perform_template_applications(env, previous_applications)?,
+                    poly.perform_template_applications(env, previous_applications, checked)?,
                     ty_args
                         .into_iter()
-                        .map(|t| t.perform_template_applications(env, previous_applications))
+                        .map(|t| t.perform_template_applications(env, previous_applications, checked))
                         .collect::<Result<Vec<_>, _>>()?,
                 );
                 if let Some(t) = previous_applications.get(&pair) {
@@ -3815,16 +4173,46 @@
                         Self::Poly(params, mono_ty) => {
                             let _poly = Self::Poly(params.clone(), mono_ty.clone());
                             let mut mono_ty = *mono_ty;
-                            for (param, ty_arg) in params.iter().zip(ty_args.iter()) {
-                                mono_ty = mono_ty.substitute(param, ty_arg);
+                            if !checked {
+                                for ((param, _expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) {
+                                    mono_ty = mono_ty.substitute(param, ty_arg);
+                                }
+                            } else {
+                                let mut new_env = env.clone();
+                                for ((param, _expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) {
+                                    new_env.define_type(param, ty_arg.clone());
+                                }
+                                for ((param, expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) {
+                                    if let Some(expected_ty) = expected_ty {
+                                        if !expected_ty.equals(ty_arg, &new_env)? && !matches!(ty_arg, Type::Unit(name, inner) if param == name || **inner == Type::None) {
+                                            return Err(Error::MismatchedTypes { expected: expected_ty.clone(), found: ty_arg.clone(), expr: Expr::ConstExpr(self.clone().into()) })
+                                        }
+                                    }
+                                    mono_ty = mono_ty.substitute(param, ty_arg);
+                                }
                             }
                             mono_ty
                         }
                         Self::Symbol(s) => match env.get_type(s.as_str()).cloned() {
                             Some(Self::Poly(params, mono_ty)) => {
                                 let mut mono_ty = *mono_ty;
-                                for (param, ty_arg) in params.iter().zip(ty_args.iter()) {
-                                    mono_ty = mono_ty.substitute(param, ty_arg);
+                                if !checked {
+                                    for ((param, _expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) {
+                                        mono_ty = mono_ty.substitute(param, ty_arg);
+                                    }
+                                } else {
+                                    let mut new_env = env.clone();
+                                    for ((param, _expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) {
+                                        new_env.define_type(param, ty_arg.clone());
+                                    }
+                                    for ((param, expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) {
+                                        if let Some(expected_ty) = expected_ty {
+                                            if !expected_ty.equals(ty_arg, &new_env)? && !matches!(ty_arg, Type::Unit(name, inner) if param == name || **inner == Type::None) {
+                                                return Err(Error::MismatchedTypes { expected: expected_ty.clone(), found: ty_arg.clone(), expr: Expr::ConstExpr(self.clone().into()) })
+                                            }
+                                        }
+                                        mono_ty = mono_ty.substitute(param, ty_arg);
+                                    }
                                 }
                                 mono_ty
                             }
@@ -3837,13 +4225,13 @@
             }
             Self::Pointer(mutability, inner) => Self::Pointer(
                 mutability,
-                Box::new(inner.perform_template_applications(env, previous_applications)?),
+                Box::new(inner.perform_template_applications(env, previous_applications, checked)?),
             ),
             Self::Proc(args, ret) => Self::Proc(
                 args.into_iter()
-                    .map(|t| t.perform_template_applications(env, previous_applications))
+                    .map(|t| t.perform_template_applications(env, previous_applications, checked))
                     .collect::<Result<Vec<_>, _>>()?,
-                Box::new(ret.perform_template_applications(env, previous_applications)?),
+                Box::new(ret.perform_template_applications(env, previous_applications, checked)?),
             ),
             Self::Struct(fields) if !self.is_recursive(env)? => Self::Struct(
                 fields
@@ -3851,7 +4239,7 @@
                     .map(|(name, t)| {
                         Ok((
                             name,
-                            t.perform_template_applications(env, previous_applications)?,
+                            t.perform_template_applications(env, previous_applications, checked)?,
                         ))
                     })
                     .collect::<Result<BTreeMap<_, _>, Error>>()?,
@@ -3862,7 +4250,7 @@
                     .map(|(name, t)| {
                         Ok((
                             name,
-                            t.perform_template_applications(env, previous_applications)?,
+                            t.perform_template_applications(env, previous_applications, checked)?,
                         ))
                     })
                     .collect::<Result<BTreeMap<_, _>, Error>>()?,
@@ -3874,21 +4262,26 @@
                     .map(|(name, t)| {
                         Ok((
                             name,
-                            t.perform_template_applications(env, previous_applications)?,
+                            t.perform_template_applications(env, previous_applications, checked)?,
                         ))
                     })
                     .collect::<Result<BTreeMap<_, _>, Error>>()?,
             ),
 
+            Self::Type(ty) if !self.is_recursive(env)? => {
+                ty.perform_template_applications(env, previous_applications, checked)?;
+                Self::Type(ty)
+            }
+
             Self::Tuple(items) if !self.is_recursive(env)? => Self::Tuple(
                 items
                     .into_iter()
-                    .map(|t| t.perform_template_applications(env, previous_applications))
+                    .map(|t| t.perform_template_applications(env, previous_applications, checked))
                     .collect::<Result<Vec<_>, _>>()?,
             ),
 
             Self::Array(item_t, size) if !self.is_recursive(env)? => Self::Array(
-                Box::new(item_t.perform_template_applications(env, previous_applications)?),
+                Box::new(item_t.perform_template_applications(env, previous_applications, checked)?),
                 size,
             ),
 
@@ -3916,7 +4309,6 @@
             );
             return Ok(false);
         }
-        trace!("Checking if {} equals {}", self, other);
 
         let i = i + 1;
 
@@ -4046,8 +4438,8 @@
             }
             (Self::Array(t1, size1), Self::Array(t2, size2)) => {
                 t1.equals_checked(t2, compared_symbols, env, i)?
-                    && size1.clone().as_int(env)? == size2.clone().as_int(env)?
-            }
+                    && size1.clone().eval(env)?.equals(&size2.clone().eval(env)?, env)
+            }
             (Self::Struct(a), Self::Struct(b)) => {
                 if a.len() != b.len() {
                     return Ok(false);
@@ -4113,8 +4505,22 @@
 
                 // Create a new environment.
                 let mut new_env = env.clone();
-                for (name1, name2) in ty_params1.iter().zip(ty_params2.iter()) {
-                    // In the new environment, bind the two type parameters to the same type.
+                for ((name1, _ty1), (name2, _ty2)) in ty_params1.iter().zip(ty_params2.iter()) {
+                    // match (ty1, ty2) {
+                    //     (Some(ty1), Some(ty2)) => {
+                    //         if !ty1.equals_checked(&ty2, compared_symbols, &new_env, i)? {
+                    //             return Err(Error::MismatchedTypes { expected: ty1.clone(), found: ty2.clone(), expr: Expr::ConstExpr(self.clone().into()) })
+                    //         }
+                    //     }
+                    //     (None, None) => {}
+                    //     (Some(ty1), None) => {
+                    //         return Err(Error::MismatchedTypes { expected: ty1.clone(), found: Self::Type(Type::Any.into()), expr: Expr::ConstExpr(self.clone().into()) })
+                    //     }
+                    //     (None, Some(ty2)) => {
+                    //         return Err(Error::UnexpectedConstParam { found: ty2.clone(), expr: Expr::ConstExpr(self.clone().into()) })
+                    //     }
+                    // }
+                    // In the new environment, bind the two type parameters to the same type.
                     let combined_name = format!("{name1}+{name2}");
                     let combined_ty = Self::Unit(combined_name, Box::new(Type::Any));
                     new_env.define_type(name1, combined_ty.clone());
@@ -4144,13 +4550,13 @@
                     true
                 } else if let Self::Poly(ty_params, template) = poly1.clone().simplify(env)? {
                     let mut template = *template.clone();
-                    for (param, arg) in ty_params.iter().zip(ty_args1.iter()) {
+                    for ((param, _), arg) in ty_params.iter().zip(ty_args1.iter()) {
                         template = template.substitute(param, arg);
                     }
                     template.equals_checked(other, compared_symbols, env, i)?
                 } else if let Self::Poly(ty_params, template) = poly2.clone().simplify(env)? {
                     let mut template = *template.clone();
-                    for (param, arg) in ty_params.iter().zip(ty_args2.iter()) {
+                    for ((param, _), arg) in ty_params.iter().zip(ty_args2.iter()) {
                         template = template.substitute(param, arg);
                     }
                     template.equals_checked(other, compared_symbols, env, i)?
@@ -4169,12 +4575,16 @@
 
             (Self::Apply(poly, ty_args), b) | (b, Self::Apply(poly, ty_args)) => {
                 Self::Apply(poly.clone(), ty_args.clone())
-                    .simplify_until_concrete(env)?
+                    .simplify_until_concrete(env, false)?
                     .equals_checked(b, compared_symbols, env, i)?
             }
 
-            _ => {
-                // trace!("{} is not equal to {}", a, b);
+            (Self::ConstParam(a), Self::ConstParam(b)) => a == b,
+            (Self::ConstParam(cexpr), other) | (other, Self::ConstParam(cexpr)) => {
+                cexpr.get_type(env)?.equals_checked(other, compared_symbols, env, i)?
+            },
+            (_a, _b) => {
+                // error!("{} is not equal to {}", a, b);
                 false
             }
         })
@@ -4189,7 +4599,7 @@
         expr: &Expr,
         env: &Env,
     ) -> Result<(Type, usize), Error> {
-        trace!("Getting offset of member {member} in expression {self} in the environment {env}");
+        debug!("Getting offset of member {member} in expression {self} in the environment {env}");
         match self {
             Type::Pointer(_, t) => t.get_member_offset(member, expr, env),
             Type::Struct(members) => {
@@ -4248,7 +4658,7 @@
             Type::Unit(_unit_name, t) => t.get_member_offset(member, expr, env),
 
             Type::Apply(_, _) | Type::Poly(_, _) => {
-                let t = self.simplify_until_concrete(env)?;
+                let t = self.simplify_until_concrete(env, false)?;
                 t.get_member_offset(member, expr, env)
             }
 
@@ -4261,6 +4671,14 @@
                 }
             }
 
+            Type::Type(ty) => {
+                if ty.is_const_param() {
+                    ty.simplify_until_const_param(env, false)?.get_type(env)?.get_member_offset(member, expr, env)
+                } else {
+                    Err(Error::MemberNotFound(expr.clone(), member.clone()))
+                }
+            }
+
             _ => Err(Error::MemberNotFound(expr.clone(), member.clone())),
         }
     }
@@ -4274,12 +4692,19 @@
         trace!("Typechecking member \"{member}\" of {expr} in {env}");
         match self {
             Type::Type(ty) => {
-                let name = member.clone().as_symbol(env)?;
-
-                if env.has_associated_const(ty, &name) {
-                    Ok(())
+                if ty.type_check_member(member, expr, env).is_ok() {
+                    return Ok(())
+                }
+                if ty.is_const_param() {
+                    ty.simplify_until_const_param(env, true)?.get_type(env)?.type_check_member(member, expr, env)
                 } else {
-                    Err(Error::MemberNotFound(expr.clone(), member.clone()))
+                    let name = member.clone().as_symbol(env)?;
+        
+                    if env.has_associated_const(ty, &name) {
+                        Ok(())
+                    } else {
+                        Err(Error::MemberNotFound(expr.clone(), member.clone()))
+                    }
                 }
             }
 
@@ -4355,7 +4780,7 @@
             }
 
             Type::Apply(_, _) | Type::Poly(_, _) => {
-                let t = self.simplify_until_concrete(env)?;
+                let t = self.simplify_until_concrete(env, true)?;
                 trace!("Simplified {self} to {t}");
                 t.type_check_member(member, expr, env)
             }
@@ -4395,7 +4820,14 @@
 
         let _s = self.to_string();
         let result = match self {
-            Self::Type(t) => Self::Type(t),
+            Self::Type(t) => {
+                if t.is_const_param() {
+                    Self::ConstParam(t.simplify_until_const_param(env, false)?.into())
+                } else {
+                    Self::Type(t.into())
+                }
+            },
+            Self::ConstParam(cexpr) => Self::ConstParam(cexpr.eval(env)?.into()),
 
             Self::None
             | Self::Never
@@ -4405,8 +4837,15 @@
             | Self::Char
             | Self::Bool
             | Self::Cell
-            | Self::Enum(_)
-            | Self::Poly(_, _) => self.clone(),
+            | Self::Enum(_) => self.clone(),
+            Self::Poly(mut ty_params, body) => {
+                for (_name, ty) in &mut ty_params {
+                    if let Some(ty) = ty {
+                        *ty = ty.clone().simplify_checked(env, i)?;
+                    }
+                }
+                Self::Poly(ty_params, body)
+            }
             Self::Pointer(mutability, inner) => {
                 Self::Pointer(mutability, Box::new(inner.simplify_checked(env, i)?))
             }
@@ -4438,12 +4877,13 @@
 
             Self::Unit(unit_name, t) => {
                 Self::Unit(unit_name, Box::new(t.simplify_checked(env, i)?))
-                // self
-            }
+            }
 
             Self::Symbol(ref name) => {
                 if let Some(t) = env.get_type(name) {
                     t.clone()
+                } else if let Some(cexpr) = env.get_const(name) {
+                    Type::ConstParam(cexpr.clone().into())
                 } else {
                     self.clone()
                 }
@@ -4456,22 +4896,47 @@
                 Box::new(ret.simplify_checked(env, i)?),
             ),
 
-            Self::Tuple(items) => Self::Tuple(
-                items
-                    .into_iter()
-                    .flat_map(|t| t.simplify_checked(env, i))
-                    .collect(),
-            ),
             Self::Array(inner, size) => Self::Array(
                 Box::new(inner.simplify_checked(env, i)?),
                 Box::new(size.eval(env)?),
             ),
-            Self::Struct(fields) => Self::Struct(
-                fields
+
+            Self::Tuple(items) => {
+                let simple_items = items
                     .into_iter()
-                    .map(|(k, t)| Ok((k, t.simplify_checked(env, i)?)))
-                    .collect::<Result<BTreeMap<String, Type>, Error>>()?,
-            ),
+                    .map(|t| t.simplify_checked(env, i))
+                    .collect::<Result<Vec<_>, Error>>()?;
+                
+                if simple_items.iter().all(Self::is_const_param) {
+                    Self::ConstParam(ConstExpr::Tuple(simple_items
+                        .into_iter()
+                        .map(|t| Ok(match t {
+                            Type::ConstParam(cexpr) => cexpr.eval(env)?,
+                            _ => unreachable!()
+                        }))
+                        .collect::<Result<_, Error>>()?).into())
+                } else {
+                    Self::Tuple(simple_items)
+                }
+            }
+            Self::Struct(fields) => {
+                let simple_fields = fields
+                    .into_iter()
+                    .map(|(name, t)| Ok((name, t.simplify_checked(env, i)?)))
+                    .collect::<Result<BTreeMap<_, _>, Error>>()?;
+                
+                if simple_fields.iter().map(|(_x, t)| t).all(Self::is_const_param) {
+                    Self::ConstParam(ConstExpr::Struct(simple_fields
+                        .into_iter()
+                        .map(|(name, t)| Ok(match t {
+                            Type::ConstParam(cexpr) => (name, cexpr.eval(env)?),
+                            _ => unreachable!()
+                        }))
+                        .collect::<Result<_, Error>>()?).into())
+                } else {
+                    Self::Struct(simple_fields)
+                }
+            }
             Self::Union(types) => Self::Union(
                 types
                     .into_iter()
@@ -4486,22 +4951,7 @@
             ),
 
             Self::Apply(poly, ty_args) => {
-                // let poly_clone = poly.clone();
-                // match *poly {
-                //     Self::Poly(params, mut result) => {
-                //         for (param, arg) in params.iter().zip(ty_args.iter()) {
-                //             *result = result.substitute(param, arg);
-                //         }
-                //         // *result = result.simplify_checked(env, i)?;
-
-                //         // Add mono type to environment
-                //         env.add_monomorphized_associated_consts(*poly_clone, *result.clone(), ty_args)?;
-                //         *result
-                //     }
-                //     _ => Self::Apply(Box::new(poly.simplify_checked(env, i)?), ty_args)
-                // }
-
-                Self::Apply(Box::new(poly.simplify_checked(env, i)?), ty_args)
+                Self::Apply(Box::new(poly.simplify_checked(env, i)?), ty_args)
             }
         };
         Ok(result)
@@ -4511,7 +4961,8 @@
 impl fmt::Display for Type {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Self::Type(t) => write!(f, "{t}"),
+            Self::ConstParam(t) => write!(f, "const param {t}"),
+            Self::Type(t) => write!(f, "type {t}"),
             Self::Any => write!(f, "Any"),
             Self::Never => write!(f, "Never"),
             Self::Pointer(mutability, ty) => {
@@ -4530,8 +4981,11 @@
             Self::Array(ty, len) => write!(f, "[{ty} * {len}]"),
             Self::Poly(ty_params, template) => {
                 write!(f, "(")?;
-                for (i, param) in ty_params.iter().enumerate() {
+                for (i, (param, ty)) in ty_params.iter().enumerate() {
                     write!(f, "{param}")?;
+                    if let Some(ty) = ty {
+                        write!(f, ": {ty}")?;
+                    }
                     if i < ty_params.len() - 1 {
                         write!(f, ", ")?
                     }
@@ -4716,6 +5170,10 @@
                 state.write_u8(21);
                 t.hash(state);
             }
+            Self::ConstParam(cexpr) => {
+                state.write_u8(22);
+                cexpr.hash(state);
+            }
         }
     }
 }
diff --git a/docs/src/sage/lir/types/size.rs.html b/docs/src/sage/lir/types/size.rs.html
index 1b409639..ffc6aa32 100644
--- a/docs/src/sage/lir/types/size.rs.html
+++ b/docs/src/sage/lir/types/size.rs.html
@@ -194,6 +194,13 @@
 193
 194
 195
+196
+197
+198
+199
+200
+201
+202
 
//! # Type Size
 //!
 //! This module contains the `GetSize` trait, which is used to calculate the size
@@ -254,7 +261,14 @@
             });
         }
 
+        if self.is_const_param() {
+            let cexpr = self.clone().simplify_until_const_param(env, false)?;
+            return cexpr.get_size_checked(env, i)
+        }
+
         let result = match self {
+            Self::ConstParam(cexpr) => cexpr.get_size_checked(env, i)?,
+
             // None or Never are not real types, so they have no size.
             // They are not represented with data. They have zero size.
             Self::Type(_) | Self::None | Self::Never => 0,
@@ -360,7 +374,7 @@
                     return Ok(size);
                 }
 
-                let result = self.clone().simplify_until_concrete(env)?;
+                let result = self.clone().simplify_until_concrete(env, false)?;
 
                 result.get_size_checked(env, i)?
             }
diff --git a/docs/src/sage/vm/std.rs.html b/docs/src/sage/vm/std.rs.html
index 7881b154..01c477d8 100644
--- a/docs/src/sage/vm/std.rs.html
+++ b/docs/src/sage/vm/std.rs.html
@@ -398,7 +398,6 @@
 397
 398
 399
-400
 
//! The standard instructions of the virtual machine are defined here.
 //!
 //! ## Purpose of the Standard Instructions
@@ -484,7 +483,6 @@
                     self.0.pop();
                     self.op(CoreOp::Set(vec![(n[0] >= 0) as i64]))
                 }
-
                 (_, op) => {
                     self.0.push(StandardOp::CoreOp(op));
                 }
diff --git a/docs/trait.impl/core/clone/trait.Clone.js b/docs/trait.impl/core/clone/trait.Clone.js
index bae39c66..fc289469 100644
--- a/docs/trait.impl/core/clone/trait.Clone.js
+++ b/docs/trait.impl/core/clone/trait.Clone.js
@@ -1,3 +1,3 @@
 (function() {var implementors = {
-"sage":[["impl Clone for Tag"],["impl Clone for Data"],["impl Clone for FFIProcedure"],["impl Clone for Declaration"],["impl Clone for Pattern"],["impl Clone for Arithmetic"],["impl Clone for CoreBuiltin"],["impl Clone for CoreOp"],["impl Clone for StandardProgram"],["impl Clone for Globals"],["impl Clone for StandardDevice"],["impl Clone for SourceCodeLocation"],["impl Clone for BitwiseNand"],["impl Clone for BitwiseNot"],["impl Clone for Assign"],["impl Clone for Error"],["impl Clone for And"],["impl Clone for New"],["impl Clone for Not"],["impl Clone for ConstExpr"],["impl Clone for StandardProgram"],["impl Clone for Put"],["impl Clone for Box<dyn TernaryOp>"],["impl Clone for Box<dyn BinaryOp>"],["impl Clone for CoreProgram"],["impl Clone for Delete"],["impl Clone for Input"],["impl Clone for Get"],["impl Clone for Env"],["impl Clone for Error"],["impl Clone for Error"],["impl Clone for Negate"],["impl Clone for BitwiseAnd"],["impl Clone for Procedure"],["impl Clone for Output"],["impl Clone for Box<dyn AssignOp>"],["impl Clone for Axis"],["impl Clone for StandardOp"],["impl Clone for BitwiseXor"],["impl Clone for FFIBinding"],["impl Clone for BitwiseNor"],["impl Clone for CoreOp"],["impl Clone for OutputMode"],["impl Clone for Direction"],["impl Clone for Channel"],["impl Clone for Mutability"],["impl Clone for Or"],["impl Clone for StandardBuiltin"],["impl Clone for CoreProgram"],["impl Clone for Color"],["impl Clone for Expr"],["impl Clone for Type"],["impl Clone for Box<dyn UnaryOp>"],["impl Clone for PolyProcedure"],["impl Clone for Add"],["impl Clone for InputMode"],["impl Clone for StandardOp"],["impl Clone for Annotation"],["impl Clone for Comparison"],["impl Clone for Location"],["impl Clone for BitwiseOr"]]
+"sage":[["impl Clone for CoreOp"],["impl Clone for CoreProgram"],["impl Clone for FFIProcedure"],["impl Clone for Direction"],["impl Clone for StandardOp"],["impl Clone for Input"],["impl Clone for CoreOp"],["impl Clone for Or"],["impl Clone for BitwiseNand"],["impl Clone for Negate"],["impl Clone for Channel"],["impl Clone for Box<dyn TernaryOp>"],["impl Clone for CoreBuiltin"],["impl Clone for CoreProgram"],["impl Clone for StandardOp"],["impl Clone for Error"],["impl Clone for And"],["impl Clone for Type"],["impl Clone for StandardDevice"],["impl Clone for Procedure"],["impl Clone for Not"],["impl Clone for StandardProgram"],["impl Clone for Error"],["impl Clone for Color"],["impl Clone for Data"],["impl Clone for Axis"],["impl Clone for Output"],["impl Clone for Delete"],["impl Clone for BitwiseAnd"],["impl Clone for BitwiseXor"],["impl Clone for Get"],["impl Clone for Box<dyn UnaryOp>"],["impl Clone for Comparison"],["impl Clone for BitwiseOr"],["impl Clone for Pattern"],["impl Clone for InputMode"],["impl Clone for OutputMode"],["impl Clone for Error"],["impl Clone for Arithmetic"],["impl Clone for Location"],["impl Clone for ConstExpr"],["impl Clone for StandardProgram"],["impl Clone for Tag"],["impl Clone for Declaration"],["impl Clone for BitwiseNor"],["impl Clone for Env"],["impl Clone for New"],["impl Clone for Assign"],["impl Clone for Add"],["impl Clone for BitwiseNot"],["impl Clone for Box<dyn AssignOp>"],["impl Clone for StandardBuiltin"],["impl Clone for SourceCodeLocation"],["impl Clone for Box<dyn BinaryOp>"],["impl Clone for Expr"],["impl Clone for Mutability"],["impl Clone for Globals"],["impl Clone for Put"],["impl Clone for PolyProcedure"],["impl Clone for FFIBinding"],["impl Clone for Annotation"]]
 };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/docs/trait.impl/core/cmp/trait.Eq.js b/docs/trait.impl/core/cmp/trait.Eq.js
index 9ede0c89..4b35c88d 100644
--- a/docs/trait.impl/core/cmp/trait.Eq.js
+++ b/docs/trait.impl/core/cmp/trait.Eq.js
@@ -1,3 +1,3 @@
 (function() {var implementors = {
-"sage":[["impl Eq for Tag"],["impl Eq for Type"],["impl Eq for BitwiseNot"],["impl Eq for SourceCodeLocation"],["impl Eq for CoreOp"],["impl Eq for BitwiseOr"],["impl Eq for Annotation"],["impl Eq for Comparison"],["impl Eq for BitwiseNor"],["impl Eq for Pattern"],["impl Eq for Input"],["impl Eq for Delete"],["impl Eq for And"],["impl Eq for Put"],["impl Eq for Get"],["impl Eq for Mutability"],["impl Eq for Direction"],["impl Eq for CoreOp"],["impl Eq for BitwiseXor"],["impl Eq for ConstExpr"],["impl Eq for Data"],["impl Eq for FFIProcedure"],["impl Eq for FFIBinding"],["impl Eq for Negate"],["impl Eq for Color"],["impl Eq for InputMode"],["impl Eq for New"],["impl Eq for StandardBuiltin"],["impl Eq for dyn BinaryOp"],["impl Eq for dyn UnaryOp"],["impl Eq for Channel"],["impl Eq for Location"],["impl Eq for Output"],["impl Eq for BitwiseNand"],["impl Eq for OutputMode"],["impl Eq for Procedure"],["impl Eq for Axis"],["impl Eq for PolyProcedure"],["impl Eq for Add"],["impl Eq for CoreProgram"],["impl Eq for dyn AssignOp"],["impl Eq for CoreBuiltin"],["impl Eq for BitwiseAnd"],["impl Eq for CoreProgram"],["impl Eq for dyn TernaryOp"]]
+"sage":[["impl Eq for CoreBuiltin"],["impl Eq for CoreOp"],["impl Eq for BitwiseNand"],["impl Eq for Location"],["impl Eq for OutputMode"],["impl Eq for Color"],["impl Eq for Procedure"],["impl Eq for Data"],["impl Eq for SourceCodeLocation"],["impl Eq for Axis"],["impl Eq for Pattern"],["impl Eq for FFIProcedure"],["impl Eq for FFIBinding"],["impl Eq for dyn AssignOp"],["impl Eq for Input"],["impl Eq for StandardBuiltin"],["impl Eq for Output"],["impl Eq for BitwiseAnd"],["impl Eq for PolyProcedure"],["impl Eq for Tag"],["impl Eq for Get"],["impl Eq for Type"],["impl Eq for CoreProgram"],["impl Eq for BitwiseOr"],["impl Eq for Delete"],["impl Eq for dyn UnaryOp"],["impl Eq for Channel"],["impl Eq for dyn BinaryOp"],["impl Eq for BitwiseNor"],["impl Eq for BitwiseNot"],["impl Eq for dyn TernaryOp"],["impl Eq for Annotation"],["impl Eq for CoreOp"],["impl Eq for BitwiseXor"],["impl Eq for Comparison"],["impl Eq for Direction"],["impl Eq for Mutability"],["impl Eq for Add"],["impl Eq for Negate"],["impl Eq for InputMode"],["impl Eq for New"],["impl Eq for Put"],["impl Eq for And"],["impl Eq for ConstExpr"],["impl Eq for CoreProgram"]]
 };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/docs/trait.impl/core/cmp/trait.Ord.js b/docs/trait.impl/core/cmp/trait.Ord.js
index ccb5759d..dafcb153 100644
--- a/docs/trait.impl/core/cmp/trait.Ord.js
+++ b/docs/trait.impl/core/cmp/trait.Ord.js
@@ -1,3 +1,3 @@
 (function() {var implementors = {
-"sage":[["impl Ord for CoreProgram"],["impl Ord for InputMode"],["impl Ord for Mutability"],["impl Ord for Input"],["impl Ord for Annotation"],["impl Ord for dyn AssignOp"],["impl Ord for dyn BinaryOp"],["impl Ord for Put"],["impl Ord for Negate"],["impl Ord for BitwiseOr"],["impl Ord for Tag"],["impl Ord for Direction"],["impl Ord for BitwiseXor"],["impl Ord for CoreProgram"],["impl Ord for BitwiseNot"],["impl Ord for Comparison"],["impl Ord for Get"],["impl Ord for Axis"],["impl Ord for Data"],["impl Ord for Output"],["impl Ord for SourceCodeLocation"],["impl Ord for FFIBinding"],["impl Ord for CoreOp"],["impl Ord for Color"],["impl Ord for BitwiseNand"],["impl Ord for And"],["impl Ord for OutputMode"],["impl Ord for Add"],["impl Ord for dyn TernaryOp"],["impl Ord for CoreOp"],["impl Ord for New"],["impl Ord for Location"],["impl Ord for dyn UnaryOp"],["impl Ord for BitwiseNor"],["impl Ord for BitwiseAnd"],["impl Ord for Delete"],["impl Ord for Channel"]]
+"sage":[["impl Ord for dyn BinaryOp"],["impl Ord for Axis"],["impl Ord for CoreProgram"],["impl Ord for BitwiseNot"],["impl Ord for BitwiseNand"],["impl Ord for dyn TernaryOp"],["impl Ord for Mutability"],["impl Ord for Channel"],["impl Ord for Negate"],["impl Ord for FFIBinding"],["impl Ord for CoreOp"],["impl Ord for InputMode"],["impl Ord for CoreOp"],["impl Ord for CoreProgram"],["impl Ord for Direction"],["impl Ord for BitwiseAnd"],["impl Ord for Put"],["impl Ord for Get"],["impl Ord for Delete"],["impl Ord for OutputMode"],["impl Ord for Input"],["impl Ord for Add"],["impl Ord for Tag"],["impl Ord for dyn UnaryOp"],["impl Ord for BitwiseOr"],["impl Ord for And"],["impl Ord for BitwiseNor"],["impl Ord for SourceCodeLocation"],["impl Ord for BitwiseXor"],["impl Ord for Comparison"],["impl Ord for Color"],["impl Ord for Data"],["impl Ord for New"],["impl Ord for Location"],["impl Ord for Annotation"],["impl Ord for dyn AssignOp"],["impl Ord for Output"]]
 };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/docs/trait.impl/core/cmp/trait.PartialEq.js b/docs/trait.impl/core/cmp/trait.PartialEq.js
index ea1e63c6..6b0f178a 100644
--- a/docs/trait.impl/core/cmp/trait.PartialEq.js
+++ b/docs/trait.impl/core/cmp/trait.PartialEq.js
@@ -1,3 +1,3 @@
 (function() {var implementors = {
-"sage":[["impl PartialEq for OutputMode"],["impl PartialEq for PolyProcedure"],["impl PartialEq for BitwiseXor"],["impl PartialEq for Delete"],["impl PartialEq for FFIBinding"],["impl PartialEq for StandardOp"],["impl PartialEq for Pattern"],["impl PartialEq for Tag"],["impl PartialEq for And"],["impl PartialEq for CoreOp"],["impl PartialEq for Get"],["impl PartialEq for CoreProgram"],["impl PartialEq for InputMode"],["impl PartialEq for Comparison"],["impl PartialEq for BitwiseNot"],["impl PartialEq for Annotation"],["impl PartialEq for Type"],["impl PartialEq for CoreProgram"],["impl PartialEq for Data"],["impl PartialEq for StandardProgram"],["impl PartialEq for dyn TernaryOp"],["impl PartialEq for Input"],["impl PartialEq for SourceCodeLocation"],["impl PartialEq for Add"],["impl PartialEq for Expr"],["impl PartialEq for Procedure"],["impl PartialEq for StandardProgram"],["impl PartialEq for BitwiseNor"],["impl PartialEq for BitwiseAnd"],["impl PartialEq for Channel"],["impl PartialEq for Mutability"],["impl PartialEq for FFIProcedure"],["impl PartialEq for dyn AssignOp"],["impl PartialEq for dyn UnaryOp"],["impl PartialEq for Negate"],["impl PartialEq for StandardBuiltin"],["impl PartialEq for CoreBuiltin"],["impl PartialEq for Error"],["impl PartialEq for BitwiseNand"],["impl PartialEq for ConstExpr"],["impl PartialEq for Output"],["impl PartialEq for Put"],["impl PartialEq for Declaration"],["impl PartialEq for Direction"],["impl PartialEq for dyn BinaryOp"],["impl PartialEq for New"],["impl PartialEq for StandardOp"],["impl PartialEq for CoreOp"],["impl PartialEq for Color"],["impl PartialEq for Location"],["impl PartialEq for Error"],["impl PartialEq for Axis"],["impl PartialEq for BitwiseOr"]]
+"sage":[["impl PartialEq for StandardProgram"],["impl PartialEq for Channel"],["impl PartialEq for dyn AssignOp"],["impl PartialEq for Axis"],["impl PartialEq for Get"],["impl PartialEq for Expr"],["impl PartialEq for StandardOp"],["impl PartialEq for CoreBuiltin"],["impl PartialEq for FFIBinding"],["impl PartialEq for Direction"],["impl PartialEq for Color"],["impl PartialEq for InputMode"],["impl PartialEq for Input"],["impl PartialEq for dyn BinaryOp"],["impl PartialEq for BitwiseAnd"],["impl PartialEq for Tag"],["impl PartialEq for CoreProgram"],["impl PartialEq for Negate"],["impl PartialEq for ConstExpr"],["impl PartialEq for Output"],["impl PartialEq for Error"],["impl PartialEq for dyn UnaryOp"],["impl PartialEq for FFIProcedure"],["impl PartialEq for Pattern"],["impl PartialEq for And"],["impl PartialEq for Type"],["impl PartialEq for StandardOp"],["impl PartialEq for New"],["impl PartialEq for Error"],["impl PartialEq for CoreOp"],["impl PartialEq for BitwiseNand"],["impl PartialEq for Put"],["impl PartialEq for PolyProcedure"],["impl PartialEq for StandardProgram"],["impl PartialEq for Comparison"],["impl PartialEq for BitwiseOr"],["impl PartialEq for dyn TernaryOp"],["impl PartialEq for CoreOp"],["impl PartialEq for Add"],["impl PartialEq for Delete"],["impl PartialEq for CoreProgram"],["impl PartialEq for BitwiseXor"],["impl PartialEq for Location"],["impl PartialEq for Annotation"],["impl PartialEq for BitwiseNor"],["impl PartialEq for StandardBuiltin"],["impl PartialEq for Data"],["impl PartialEq for Procedure"],["impl PartialEq for Declaration"],["impl PartialEq for OutputMode"],["impl PartialEq for Mutability"],["impl PartialEq for SourceCodeLocation"],["impl PartialEq for BitwiseNot"]]
 };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/docs/trait.impl/core/cmp/trait.PartialOrd.js b/docs/trait.impl/core/cmp/trait.PartialOrd.js
index 36a874bd..5c3202e3 100644
--- a/docs/trait.impl/core/cmp/trait.PartialOrd.js
+++ b/docs/trait.impl/core/cmp/trait.PartialOrd.js
@@ -1,3 +1,3 @@
 (function() {var implementors = {
-"sage":[["impl PartialOrd for dyn AssignOp"],["impl PartialOrd for BitwiseOr"],["impl PartialOrd for New"],["impl PartialOrd for BitwiseNand"],["impl PartialOrd for BitwiseNot"],["impl PartialOrd for CoreOp"],["impl PartialOrd for Put"],["impl PartialOrd for Delete"],["impl PartialOrd for FFIBinding"],["impl PartialOrd for Negate"],["impl PartialOrd for Axis"],["impl PartialOrd for Error"],["impl PartialOrd for CoreProgram"],["impl PartialOrd for StandardProgram"],["impl PartialOrd for InputMode"],["impl PartialOrd for StandardProgram"],["impl PartialOrd for Input"],["impl PartialOrd for Mutability"],["impl PartialOrd for Location"],["impl PartialOrd for Channel"],["impl PartialOrd for Annotation"],["impl PartialOrd for BitwiseXor"],["impl PartialOrd for StandardOp"],["impl PartialOrd for Comparison"],["impl PartialOrd for Data"],["impl PartialOrd for Direction"],["impl PartialOrd for Add"],["impl PartialOrd for Error"],["impl PartialOrd for StandardOp"],["impl PartialOrd for CoreOp"],["impl PartialOrd for Tag"],["impl PartialOrd for Output"],["impl PartialOrd for SourceCodeLocation"],["impl PartialOrd for dyn UnaryOp"],["impl PartialOrd for And"],["impl PartialOrd for CoreProgram"],["impl PartialOrd for dyn TernaryOp"],["impl PartialOrd for BitwiseAnd"],["impl PartialOrd for OutputMode"],["impl PartialOrd for dyn BinaryOp"],["impl PartialOrd for Color"],["impl PartialOrd for Get"],["impl PartialOrd for BitwiseNor"]]
+"sage":[["impl PartialOrd for InputMode"],["impl PartialOrd for Annotation"],["impl PartialOrd for StandardOp"],["impl PartialOrd for CoreOp"],["impl PartialOrd for Output"],["impl PartialOrd for Delete"],["impl PartialOrd for dyn TernaryOp"],["impl PartialOrd for CoreProgram"],["impl PartialOrd for Location"],["impl PartialOrd for Mutability"],["impl PartialOrd for StandardProgram"],["impl PartialOrd for StandardProgram"],["impl PartialOrd for Error"],["impl PartialOrd for Comparison"],["impl PartialOrd for Error"],["impl PartialOrd for BitwiseNand"],["impl PartialOrd for FFIBinding"],["impl PartialOrd for BitwiseAnd"],["impl PartialOrd for dyn AssignOp"],["impl PartialOrd for dyn UnaryOp"],["impl PartialOrd for Data"],["impl PartialOrd for BitwiseNot"],["impl PartialOrd for Get"],["impl PartialOrd for Add"],["impl PartialOrd for CoreOp"],["impl PartialOrd for Input"],["impl PartialOrd for Axis"],["impl PartialOrd for And"],["impl PartialOrd for dyn BinaryOp"],["impl PartialOrd for SourceCodeLocation"],["impl PartialOrd for Negate"],["impl PartialOrd for New"],["impl PartialOrd for CoreProgram"],["impl PartialOrd for Tag"],["impl PartialOrd for OutputMode"],["impl PartialOrd for StandardOp"],["impl PartialOrd for BitwiseNor"],["impl PartialOrd for Channel"],["impl PartialOrd for Direction"],["impl PartialOrd for Put"],["impl PartialOrd for BitwiseOr"],["impl PartialOrd for BitwiseXor"],["impl PartialOrd for Color"]]
 };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})()
\ No newline at end of file
diff --git a/docs/trait.impl/core/convert/trait.From.js b/docs/trait.impl/core/convert/trait.From.js
index f8d1eb70..32e9390e 100644
--- a/docs/trait.impl/core/convert/trait.From.js
+++ b/docs/trait.impl/core/convert/trait.From.js
@@ -1,3 +1,3 @@
 (function() {var implementors = {
-"sage":[["impl From<Mutability> for bool"],["impl From<(&str, Mutability, Option<Type>, Expr)> for Declaration"],["impl From<CoreProgram> for StandardProgram"],["impl From<(&str, Mutability, Expr)> for Declaration"],["impl From<ConstExpr> for Expr"],["impl From<(&str, FFIProcedure)> for Declaration"],["impl From<bool> for Mutability"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<(Pattern, Expr)> for Declaration"],["impl<T> From<Vec<T>> for Declaration
where\n T: Into<Declaration>,
"],["impl From<(String, ConstExpr)> for Declaration"],["impl From<(String, Procedure)> for Declaration"],["impl From<(String, PolyProcedure)> for Declaration"],["impl From<(String, Mutability, Expr)> for Declaration"],["impl From<CoreProgram> for StandardProgram"],["impl From<(String, Type)> for Declaration"],["impl From<(&str, ConstExpr)> for Declaration"],["impl From<(String, Expr)> for Declaration"],["impl From<(&str, Type)> for Declaration"],["impl From<(String, FFIProcedure)> for Declaration"],["impl From<(&str, Mutability, Type, Expr)> for Declaration"],["impl From<(&str, Expr)> for Declaration"],["impl From<SourceCodeLocation> for Annotation"],["impl From<(String, Mutability, Option<Type>, Expr)> for Declaration"],["impl<K, V> From<BTreeMap<K, V>> for Declaration"],["impl From<Box<Declaration>> for Declaration"],["impl From<(&str, Procedure)> for Declaration"],["impl From<(String, Mutability, Type, Expr)> for Declaration"],["impl From<(&str, PolyProcedure)> for Declaration"]] +"sage":[["impl<K, V> From<BTreeMap<K, V>> for Declaration"],["impl From<Procedure> for ConstExpr"],["impl From<ConstExpr> for Expr"],["impl From<(&str, Procedure)> for Declaration"],["impl From<Type> for ConstExpr"],["impl From<Box<Declaration>> for Declaration"],["impl From<PolyProcedure> for ConstExpr"],["impl From<(String, Type)> for Declaration"],["impl From<(&str, Type)> for Declaration"],["impl From<(String, Expr)> for Declaration"],["impl From<bool> for Mutability"],["impl From<(&str, Expr)> for Declaration"],["impl From<(String, Mutability, Expr)> for Declaration"],["impl From<(&str, Mutability, Option<Type>, Expr)> for Declaration"],["impl From<(&str, ConstExpr)> for Declaration"],["impl From<Error> for Error"],["impl From<CoreProgram> for StandardProgram"],["impl From<(&str, FFIProcedure)> for Declaration"],["impl From<(String, ConstExpr)> for Declaration"],["impl From<(String, Mutability, Type, Expr)> for Declaration"],["impl From<(Pattern, Expr)> for Declaration"],["impl From<(String, Mutability, Option<Type>, Expr)> for Declaration"],["impl From<SourceCodeLocation> for Annotation"],["impl From<Error> for Error"],["impl From<(&str, Mutability, Expr)> for Declaration"],["impl From<(String, Procedure)> for Declaration"],["impl From<(&str, Mutability, Type, Expr)> for Declaration"],["impl From<CoreProgram> for StandardProgram"],["impl<T> From<Vec<T>> for Declaration
where\n T: Into<Declaration>,
"],["impl From<(&str, PolyProcedure)> for Declaration"],["impl From<(String, PolyProcedure)> for Declaration"],["impl From<(String, FFIProcedure)> for Declaration"],["impl From<Mutability> for bool"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/default/trait.Default.js b/docs/trait.impl/core/default/trait.Default.js index 96d884ca..4786fd5b 100644 --- a/docs/trait.impl/core/default/trait.Default.js +++ b/docs/trait.impl/core/default/trait.Default.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"sage":[["impl Default for C"],["impl Default for Mutability"],["impl Default for CoreProgram"],["impl Default for StandardInterpreter<StandardDevice>"],["impl Default for StandardProgram"],["impl Default for Env"],["impl Default for StandardDevice"],["impl Default for StandardProgram"],["impl Default for CoreProgram"],["impl Default for Globals"],["impl Default for CoreInterpreter<StandardDevice>"],["impl Default for TestingDevice"]] +"sage":[["impl Default for CoreInterpreter<StandardDevice>"],["impl Default for C"],["impl Default for Globals"],["impl Default for StandardProgram"],["impl Default for StandardInterpreter<StandardDevice>"],["impl Default for StandardDevice"],["impl Default for Env"],["impl Default for CoreProgram"],["impl Default for TestingDevice"],["impl Default for CoreProgram"],["impl Default for Mutability"],["impl Default for StandardProgram"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/fmt/trait.Debug.js b/docs/trait.impl/core/fmt/trait.Debug.js index c03598e8..fd185731 100644 --- a/docs/trait.impl/core/fmt/trait.Debug.js +++ b/docs/trait.impl/core/fmt/trait.Debug.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"sage":[["impl Debug for Color"],["impl Debug for New"],["impl Debug for And"],["impl Debug for StandardOp"],["impl Debug for Channel"],["impl Debug for Negate"],["impl Debug for Tag"],["impl Debug for Get"],["impl Debug for Error"],["impl Debug for BitwiseNot"],["impl Debug for StandardProgram"],["impl Debug for BitwiseXor"],["impl Debug for Mutability"],["impl Debug for SourceCodeLocation"],["impl Debug for Comparison"],["impl Debug for TestingDevice"],["impl Debug for Error"],["impl Debug for Type"],["impl Debug for StandardBuiltin"],["impl Debug for BitwiseAnd"],["impl Debug for CoreBuiltin"],["impl Debug for Axis"],["impl Debug for Expr"],["impl Debug for CoreOp"],["impl Debug for Procedure"],["impl Debug for Data"],["impl Debug for Not"],["impl Debug for Input"],["impl Debug for Globals"],["impl Debug for Or"],["impl Debug for PolyProcedure"],["impl Debug for Assign"],["impl Debug for Declaration"],["impl Debug for FFIProcedure"],["impl Debug for BitwiseOr"],["impl Debug for BitwiseNand"],["impl Debug for ConstExpr"],["impl Debug for BitwiseNor"],["impl Debug for InputMode"],["impl Debug for CoreOp"],["impl Debug for StandardDevice"],["impl Debug for StandardOp"],["impl Debug for Location"],["impl Debug for FFIBinding"],["impl Debug for Add"],["impl Debug for Env"],["impl Debug for Output"],["impl Debug for Error"],["impl Debug for Delete"],["impl Debug for Put"],["impl Debug for Pattern"],["impl Debug for Arithmetic"],["impl Debug for Direction"],["impl Debug for OutputMode"],["impl Debug for Annotation"],["impl Debug for CoreProgram"]] +"sage":[["impl Debug for Type"],["impl Debug for CoreOp"],["impl Debug for Direction"],["impl Debug for Tag"],["impl Debug for CoreOp"],["impl Debug for StandardDevice"],["impl Debug for Expr"],["impl Debug for Not"],["impl Debug for Data"],["impl Debug for StandardOp"],["impl Debug for Env"],["impl Debug for FFIBinding"],["impl Debug for StandardProgram"],["impl Debug for FFIProcedure"],["impl Debug for Comparison"],["impl Debug for Mutability"],["impl Debug for Pattern"],["impl Debug for Error"],["impl Debug for Location"],["impl Debug for Negate"],["impl Debug for Assign"],["impl Debug for InputMode"],["impl Debug for BitwiseNot"],["impl Debug for Procedure"],["impl Debug for StandardBuiltin"],["impl Debug for Delete"],["impl Debug for Error"],["impl Debug for Arithmetic"],["impl Debug for New"],["impl Debug for BitwiseNand"],["impl Debug for BitwiseOr"],["impl Debug for Axis"],["impl Debug for TestingDevice"],["impl Debug for Color"],["impl Debug for Input"],["impl Debug for PolyProcedure"],["impl Debug for Add"],["impl Debug for StandardOp"],["impl Debug for OutputMode"],["impl Debug for Get"],["impl Debug for Put"],["impl Debug for Output"],["impl Debug for CoreProgram"],["impl Debug for ConstExpr"],["impl Debug for And"],["impl Debug for BitwiseAnd"],["impl Debug for Channel"],["impl Debug for BitwiseXor"],["impl Debug for Error"],["impl Debug for Or"],["impl Debug for BitwiseNor"],["impl Debug for CoreBuiltin"],["impl Debug for SourceCodeLocation"],["impl Debug for Globals"],["impl Debug for Declaration"],["impl Debug for Annotation"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/fmt/trait.Display.js b/docs/trait.impl/core/fmt/trait.Display.js index bdba6fab..51315b09 100644 --- a/docs/trait.impl/core/fmt/trait.Display.js +++ b/docs/trait.impl/core/fmt/trait.Display.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"sage":[["impl Display for CoreProgram"],["impl Display for StandardProgram"],["impl Display for Output"],["impl Display for FFIProcedure"],["impl Display for Delete"],["impl Display for Globals"],["impl Display for BitwiseOr"],["impl Display for Add"],["impl Display for Assign"],["impl Display for Procedure"],["impl Display for Not"],["impl Display for Error"],["impl Display for Input"],["impl Display for Put"],["impl Display for StandardProgram"],["impl Display for And"],["impl Display for Channel"],["impl Display for Direction"],["impl Display for Get"],["impl Display for New"],["impl Display for Expr"],["impl Display for BitwiseAnd"],["impl Display for CoreProgram"],["impl Display for Data"],["impl Display for Comparison"],["impl Display for BitwiseNand"],["impl Display for CoreBuiltin"],["impl Display for Color"],["impl Display for Error"],["impl Display for OutputMode"],["impl Display for StandardOp"],["impl Display for StandardOp"],["impl Display for Env"],["impl Display for Declaration"],["impl Display for Pattern"],["impl Display for Mutability"],["impl Display for BitwiseXor"],["impl Display for Tag"],["impl Display for Error"],["impl Display for Or"],["impl Display for StandardBuiltin"],["impl Display for Location"],["impl Display for FFIBinding"],["impl Display for InputMode"],["impl Display for Negate"],["impl Display for BitwiseNor"],["impl Display for PolyProcedure"],["impl Display for Arithmetic"],["impl Display for Type"],["impl Display for BitwiseNot"],["impl Display for Axis"],["impl Display for ConstExpr"],["impl Display for CoreOp"],["impl Display for CoreOp"]] +"sage":[["impl Display for CoreOp"],["impl Display for Declaration"],["impl Display for StandardOp"],["impl Display for Error"],["impl Display for Data"],["impl Display for Channel"],["impl Display for Or"],["impl Display for BitwiseNand"],["impl Display for Tag"],["impl Display for StandardOp"],["impl Display for Put"],["impl Display for ConstExpr"],["impl Display for Delete"],["impl Display for BitwiseNot"],["impl Display for StandardProgram"],["impl Display for BitwiseAnd"],["impl Display for PolyProcedure"],["impl Display for Arithmetic"],["impl Display for Expr"],["impl Display for New"],["impl Display for OutputMode"],["impl Display for BitwiseNor"],["impl Display for Axis"],["impl Display for Direction"],["impl Display for Add"],["impl Display for Pattern"],["impl Display for BitwiseOr"],["impl Display for Type"],["impl Display for Not"],["impl Display for Procedure"],["impl Display for InputMode"],["impl Display for CoreProgram"],["impl Display for And"],["impl Display for CoreBuiltin"],["impl Display for Output"],["impl Display for Negate"],["impl Display for Mutability"],["impl Display for Get"],["impl Display for Color"],["impl Display for FFIProcedure"],["impl Display for Error"],["impl Display for CoreProgram"],["impl Display for Assign"],["impl Display for StandardProgram"],["impl Display for Env"],["impl Display for Error"],["impl Display for Globals"],["impl Display for Location"],["impl Display for FFIBinding"],["impl Display for Input"],["impl Display for Comparison"],["impl Display for StandardBuiltin"],["impl Display for BitwiseXor"],["impl Display for CoreOp"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/hash/trait.Hash.js b/docs/trait.impl/core/hash/trait.Hash.js index 823c22ad..c5da6cf3 100644 --- a/docs/trait.impl/core/hash/trait.Hash.js +++ b/docs/trait.impl/core/hash/trait.Hash.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"sage":[["impl Hash for Tag"],["impl Hash for PolyProcedure"],["impl Hash for Delete"],["impl Hash for Location"],["impl Hash for Input"],["impl Hash for BitwiseNot"],["impl Hash for Color"],["impl Hash for ConstExpr"],["impl Hash for Direction"],["impl Hash for Comparison"],["impl Hash for Type"],["impl Hash for Negate"],["impl Hash for BitwiseOr"],["impl Hash for FFIProcedure"],["impl Hash for BitwiseXor"],["impl Hash for SourceCodeLocation"],["impl Hash for CoreProgram"],["impl Hash for Add"],["impl Hash for Procedure"],["impl Hash for StandardBuiltin"],["impl Hash for OutputMode"],["impl Hash for CoreOp"],["impl Hash for And"],["impl Hash for Pattern"],["impl Hash for Axis"],["impl Hash for New"],["impl Hash for BitwiseAnd"],["impl Hash for Declaration"],["impl Hash for BitwiseNand"],["impl Hash for Channel"],["impl Hash for Get"],["impl Hash for Mutability"],["impl Hash for Annotation"],["impl Hash for Expr"],["impl Hash for FFIBinding"],["impl Hash for CoreBuiltin"],["impl Hash for Output"],["impl Hash for CoreOp"],["impl Hash for Put"],["impl Hash for BitwiseNor"],["impl Hash for Data"],["impl Hash for InputMode"],["impl Hash for CoreProgram"]] +"sage":[["impl Hash for Type"],["impl Hash for Declaration"],["impl Hash for Pattern"],["impl Hash for Expr"],["impl Hash for OutputMode"],["impl Hash for BitwiseNot"],["impl Hash for FFIBinding"],["impl Hash for BitwiseOr"],["impl Hash for BitwiseXor"],["impl Hash for BitwiseNor"],["impl Hash for CoreOp"],["impl Hash for StandardBuiltin"],["impl Hash for Get"],["impl Hash for CoreOp"],["impl Hash for Delete"],["impl Hash for New"],["impl Hash for Location"],["impl Hash for Axis"],["impl Hash for Output"],["impl Hash for Annotation"],["impl Hash for Data"],["impl Hash for Mutability"],["impl Hash for PolyProcedure"],["impl Hash for Direction"],["impl Hash for Put"],["impl Hash for Input"],["impl Hash for Color"],["impl Hash for BitwiseNand"],["impl Hash for ConstExpr"],["impl Hash for Add"],["impl Hash for Channel"],["impl Hash for And"],["impl Hash for Comparison"],["impl Hash for FFIProcedure"],["impl Hash for CoreBuiltin"],["impl Hash for CoreProgram"],["impl Hash for CoreProgram"],["impl Hash for Tag"],["impl Hash for SourceCodeLocation"],["impl Hash for BitwiseAnd"],["impl Hash for InputMode"],["impl Hash for Procedure"],["impl Hash for Negate"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/marker/trait.Copy.js b/docs/trait.impl/core/marker/trait.Copy.js index 685245a5..e2f94b39 100644 --- a/docs/trait.impl/core/marker/trait.Copy.js +++ b/docs/trait.impl/core/marker/trait.Copy.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"sage":[["impl Copy for Direction"],["impl Copy for Get"],["impl Copy for New"],["impl Copy for Put"],["impl Copy for Data"],["impl Copy for Add"],["impl Copy for Channel"],["impl Copy for Delete"],["impl Copy for BitwiseXor"],["impl Copy for BitwiseAnd"],["impl Copy for Tag"],["impl Copy for Not"],["impl Copy for BitwiseOr"],["impl Copy for BitwiseNor"],["impl Copy for And"],["impl Copy for BitwiseNot"],["impl Copy for Color"],["impl Copy for Arithmetic"],["impl Copy for Mutability"],["impl Copy for Axis"],["impl Copy for Or"],["impl Copy for Comparison"],["impl Copy for Negate"],["impl Copy for BitwiseNand"]] +"sage":[["impl Copy for BitwiseXor"],["impl Copy for Not"],["impl Copy for BitwiseOr"],["impl Copy for Axis"],["impl Copy for Delete"],["impl Copy for Direction"],["impl Copy for BitwiseAnd"],["impl Copy for Put"],["impl Copy for Negate"],["impl Copy for Color"],["impl Copy for Add"],["impl Copy for Mutability"],["impl Copy for BitwiseNot"],["impl Copy for Data"],["impl Copy for Or"],["impl Copy for Arithmetic"],["impl Copy for Tag"],["impl Copy for New"],["impl Copy for BitwiseNand"],["impl Copy for Comparison"],["impl Copy for And"],["impl Copy for Get"],["impl Copy for Channel"],["impl Copy for BitwiseNor"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/marker/trait.Send.js b/docs/trait.impl/core/marker/trait.Send.js index 43b7655f..1875980b 100644 --- a/docs/trait.impl/core/marker/trait.Send.js +++ b/docs/trait.impl/core/marker/trait.Send.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"sage":[["impl Send for CoreProgram",1,["sage::asm::core::CoreProgram"]],["impl Send for CoreOp",1,["sage::asm::core::CoreOp"]],["impl Send for Globals",1,["sage::asm::globals::Globals"]],["impl Send for Location",1,["sage::asm::location::Location"]],["impl Send for StandardProgram",1,["sage::asm::std::StandardProgram"]],["impl Send for StandardOp",1,["sage::asm::std::StandardOp"]],["impl Send for Error",1,["sage::asm::Error"]],["impl Send for Annotation",1,["sage::lir::annotate::Annotation"]],["impl Send for Env",1,["sage::lir::env::Env"]],["impl Send for Error",1,["sage::lir::error::Error"]],["impl Send for Declaration",1,["sage::lir::expr::declaration::Declaration"]],["impl Send for Expr",1,["sage::lir::expr::expression::Expr"]],["impl Send for Add",1,["sage::lir::expr::ops::arithmetic::addition::Add"]],["impl Send for Negate",1,["sage::lir::expr::ops::arithmetic::negate::Negate"]],["impl Send for Arithmetic",1,["sage::lir::expr::ops::arithmetic::Arithmetic"]],["impl Send for Assign",1,["sage::lir::expr::ops::assign::Assign"]],["impl Send for BitwiseAnd",1,["sage::lir::expr::ops::bitwise::and::BitwiseAnd"]],["impl Send for BitwiseNand",1,["sage::lir::expr::ops::bitwise::nand::BitwiseNand"]],["impl Send for BitwiseNor",1,["sage::lir::expr::ops::bitwise::nor::BitwiseNor"]],["impl Send for BitwiseNot",1,["sage::lir::expr::ops::bitwise::not::BitwiseNot"]],["impl Send for BitwiseOr",1,["sage::lir::expr::ops::bitwise::or::BitwiseOr"]],["impl Send for BitwiseXor",1,["sage::lir::expr::ops::bitwise::xor::BitwiseXor"]],["impl Send for Comparison",1,["sage::lir::expr::ops::comparison::Comparison"]],["impl Send for Get",1,["sage::lir::expr::ops::io::Get"]],["impl Send for Put",1,["sage::lir::expr::ops::io::Put"]],["impl Send for And",1,["sage::lir::expr::ops::logic::And"]],["impl Send for Or",1,["sage::lir::expr::ops::logic::Or"]],["impl Send for Not",1,["sage::lir::expr::ops::logic::Not"]],["impl Send for New",1,["sage::lir::expr::ops::memory::New"]],["impl Send for Delete",1,["sage::lir::expr::ops::memory::Delete"]],["impl Send for Tag",1,["sage::lir::expr::ops::tagged_union::Tag"]],["impl Send for Data",1,["sage::lir::expr::ops::tagged_union::Data"]],["impl Send for Pattern",1,["sage::lir::expr::pattern::Pattern"]],["impl Send for CoreBuiltin",1,["sage::lir::expr::procedure::builtin::CoreBuiltin"]],["impl Send for StandardBuiltin",1,["sage::lir::expr::procedure::builtin::StandardBuiltin"]],["impl Send for FFIProcedure",1,["sage::lir::expr::procedure::ffi::FFIProcedure"]],["impl Send for Procedure",1,["sage::lir::expr::procedure::mono::Procedure"]],["impl Send for PolyProcedure",1,["sage::lir::expr::procedure::poly::PolyProcedure"]],["impl Send for Mutability",1,["sage::lir::types::Mutability"]],["impl Send for SourceCodeLocation",1,["sage::parse::SourceCodeLocation"]],["impl Send for FFIBinding",1,["sage::side_effects::ffi::FFIBinding"]],["impl Send for Axis",1,["sage::side_effects::io::Axis"]],["impl Send for Direction",1,["sage::side_effects::io::Direction"]],["impl Send for Color",1,["sage::side_effects::io::Color"]],["impl Send for InputMode",1,["sage::side_effects::io::InputMode"]],["impl Send for OutputMode",1,["sage::side_effects::io::OutputMode"]],["impl Send for Channel",1,["sage::side_effects::io::Channel"]],["impl Send for Input",1,["sage::side_effects::io::Input"]],["impl Send for Output",1,["sage::side_effects::io::Output"]],["impl Send for C",1,["sage::targets::c::C"]],["impl Send for CoreProgram",1,["sage::vm::core::CoreProgram"]],["impl Send for CoreOp",1,["sage::vm::core::CoreOp"]],["impl Send for StandardProgram",1,["sage::vm::std::StandardProgram"]],["impl Send for StandardOp",1,["sage::vm::std::StandardOp"]],["impl<T> Send for CoreInterpreter<T>
where\n T: Send,
",1,["sage::vm::interpreter::core::CoreInterpreter"]],["impl<T> Send for StandardInterpreter<T>
where\n T: Send,
",1,["sage::vm::interpreter::std::StandardInterpreter"]],["impl Send for TestingDevice",1,["sage::vm::interpreter::TestingDevice"]],["impl Send for StandardDevice",1,["sage::vm::interpreter::StandardDevice"]],["impl Send for Error",1,["sage::vm::Error"]],["impl Send for Type"],["impl Send for ConstExpr"]] +"sage":[["impl Send for CoreProgram",1,["sage::asm::core::CoreProgram"]],["impl Send for CoreOp",1,["sage::asm::core::CoreOp"]],["impl Send for Globals",1,["sage::asm::globals::Globals"]],["impl Send for Location",1,["sage::asm::location::Location"]],["impl Send for StandardProgram",1,["sage::asm::std::StandardProgram"]],["impl Send for StandardOp",1,["sage::asm::std::StandardOp"]],["impl Send for Error",1,["sage::asm::Error"]],["impl Send for Annotation",1,["sage::lir::annotate::Annotation"]],["impl Send for Env",1,["sage::lir::env::Env"]],["impl Send for Error",1,["sage::lir::error::Error"]],["impl Send for Declaration",1,["sage::lir::expr::declaration::Declaration"]],["impl Send for Expr",1,["sage::lir::expr::expression::Expr"]],["impl Send for Add",1,["sage::lir::expr::ops::arithmetic::addition::Add"]],["impl Send for Negate",1,["sage::lir::expr::ops::arithmetic::negate::Negate"]],["impl Send for Arithmetic",1,["sage::lir::expr::ops::arithmetic::Arithmetic"]],["impl Send for Assign",1,["sage::lir::expr::ops::assign::Assign"]],["impl Send for BitwiseAnd",1,["sage::lir::expr::ops::bitwise::and::BitwiseAnd"]],["impl Send for BitwiseNand",1,["sage::lir::expr::ops::bitwise::nand::BitwiseNand"]],["impl Send for BitwiseNor",1,["sage::lir::expr::ops::bitwise::nor::BitwiseNor"]],["impl Send for BitwiseNot",1,["sage::lir::expr::ops::bitwise::not::BitwiseNot"]],["impl Send for BitwiseOr",1,["sage::lir::expr::ops::bitwise::or::BitwiseOr"]],["impl Send for BitwiseXor",1,["sage::lir::expr::ops::bitwise::xor::BitwiseXor"]],["impl Send for Comparison",1,["sage::lir::expr::ops::comparison::Comparison"]],["impl Send for Get",1,["sage::lir::expr::ops::io::Get"]],["impl Send for Put",1,["sage::lir::expr::ops::io::Put"]],["impl Send for And",1,["sage::lir::expr::ops::logic::And"]],["impl Send for Or",1,["sage::lir::expr::ops::logic::Or"]],["impl Send for Not",1,["sage::lir::expr::ops::logic::Not"]],["impl Send for New",1,["sage::lir::expr::ops::memory::New"]],["impl Send for Delete",1,["sage::lir::expr::ops::memory::Delete"]],["impl Send for Tag",1,["sage::lir::expr::ops::tagged_union::Tag"]],["impl Send for Data",1,["sage::lir::expr::ops::tagged_union::Data"]],["impl Send for Pattern",1,["sage::lir::expr::pattern::Pattern"]],["impl Send for CoreBuiltin",1,["sage::lir::expr::procedure::builtin::CoreBuiltin"]],["impl Send for StandardBuiltin",1,["sage::lir::expr::procedure::builtin::StandardBuiltin"]],["impl Send for FFIProcedure",1,["sage::lir::expr::procedure::ffi::FFIProcedure"]],["impl Send for Procedure",1,["sage::lir::expr::procedure::mono::Procedure"]],["impl Send for PolyProcedure",1,["sage::lir::expr::procedure::poly::PolyProcedure"]],["impl Send for Mutability",1,["sage::lir::types::Mutability"]],["impl Send for SourceCodeLocation",1,["sage::parse::SourceCodeLocation"]],["impl Send for FFIBinding",1,["sage::side_effects::ffi::FFIBinding"]],["impl Send for Axis",1,["sage::side_effects::io::Axis"]],["impl Send for Direction",1,["sage::side_effects::io::Direction"]],["impl Send for Color",1,["sage::side_effects::io::Color"]],["impl Send for InputMode",1,["sage::side_effects::io::InputMode"]],["impl Send for OutputMode",1,["sage::side_effects::io::OutputMode"]],["impl Send for Channel",1,["sage::side_effects::io::Channel"]],["impl Send for Input",1,["sage::side_effects::io::Input"]],["impl Send for Output",1,["sage::side_effects::io::Output"]],["impl Send for C",1,["sage::targets::c::C"]],["impl Send for CoreProgram",1,["sage::vm::core::CoreProgram"]],["impl Send for CoreOp",1,["sage::vm::core::CoreOp"]],["impl Send for StandardProgram",1,["sage::vm::std::StandardProgram"]],["impl Send for StandardOp",1,["sage::vm::std::StandardOp"]],["impl<T> Send for CoreInterpreter<T>
where\n T: Send,
",1,["sage::vm::interpreter::core::CoreInterpreter"]],["impl<T> Send for StandardInterpreter<T>
where\n T: Send,
",1,["sage::vm::interpreter::std::StandardInterpreter"]],["impl Send for TestingDevice",1,["sage::vm::interpreter::TestingDevice"]],["impl Send for StandardDevice",1,["sage::vm::interpreter::StandardDevice"]],["impl Send for Error",1,["sage::vm::Error"]],["impl Send for ConstExpr"],["impl Send for Type"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/marker/trait.StructuralEq.js b/docs/trait.impl/core/marker/trait.StructuralEq.js index 80f137ff..724e269f 100644 --- a/docs/trait.impl/core/marker/trait.StructuralEq.js +++ b/docs/trait.impl/core/marker/trait.StructuralEq.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"sage":[["impl StructuralEq for Tag"],["impl StructuralEq for CoreOp"],["impl StructuralEq for Output"],["impl StructuralEq for InputMode"],["impl StructuralEq for And"],["impl StructuralEq for CoreOp"],["impl StructuralEq for Channel"],["impl StructuralEq for BitwiseAnd"],["impl StructuralEq for Annotation"],["impl StructuralEq for BitwiseNot"],["impl StructuralEq for CoreProgram"],["impl StructuralEq for New"],["impl StructuralEq for Data"],["impl StructuralEq for BitwiseNand"],["impl StructuralEq for Get"],["impl StructuralEq for BitwiseNor"],["impl StructuralEq for FFIProcedure"],["impl StructuralEq for Negate"],["impl StructuralEq for Comparison"],["impl StructuralEq for CoreProgram"],["impl StructuralEq for Direction"],["impl StructuralEq for BitwiseXor"],["impl StructuralEq for Put"],["impl StructuralEq for Pattern"],["impl StructuralEq for OutputMode"],["impl StructuralEq for SourceCodeLocation"],["impl StructuralEq for Location"],["impl StructuralEq for Input"],["impl StructuralEq for Mutability"],["impl StructuralEq for Color"],["impl StructuralEq for Delete"],["impl StructuralEq for Add"],["impl StructuralEq for BitwiseOr"],["impl StructuralEq for Axis"],["impl StructuralEq for FFIBinding"]] +"sage":[["impl StructuralEq for Location"],["impl StructuralEq for Negate"],["impl StructuralEq for Comparison"],["impl StructuralEq for Data"],["impl StructuralEq for Pattern"],["impl StructuralEq for And"],["impl StructuralEq for Add"],["impl StructuralEq for InputMode"],["impl StructuralEq for Get"],["impl StructuralEq for Mutability"],["impl StructuralEq for BitwiseXor"],["impl StructuralEq for Tag"],["impl StructuralEq for OutputMode"],["impl StructuralEq for Direction"],["impl StructuralEq for Put"],["impl StructuralEq for Delete"],["impl StructuralEq for Output"],["impl StructuralEq for FFIProcedure"],["impl StructuralEq for BitwiseNand"],["impl StructuralEq for BitwiseAnd"],["impl StructuralEq for Axis"],["impl StructuralEq for BitwiseNor"],["impl StructuralEq for SourceCodeLocation"],["impl StructuralEq for BitwiseOr"],["impl StructuralEq for Input"],["impl StructuralEq for CoreProgram"],["impl StructuralEq for Color"],["impl StructuralEq for FFIBinding"],["impl StructuralEq for CoreOp"],["impl StructuralEq for CoreProgram"],["impl StructuralEq for Channel"],["impl StructuralEq for CoreOp"],["impl StructuralEq for Annotation"],["impl StructuralEq for BitwiseNot"],["impl StructuralEq for New"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/core/marker/trait.StructuralPartialEq.js b/docs/trait.impl/core/marker/trait.StructuralPartialEq.js index 56ee39b7..1ee87859 100644 --- a/docs/trait.impl/core/marker/trait.StructuralPartialEq.js +++ b/docs/trait.impl/core/marker/trait.StructuralPartialEq.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"sage":[["impl StructuralPartialEq for CoreOp"],["impl StructuralPartialEq for BitwiseNor"],["impl StructuralPartialEq for Data"],["impl StructuralPartialEq for FFIProcedure"],["impl StructuralPartialEq for BitwiseNot"],["impl StructuralPartialEq for BitwiseOr"],["impl StructuralPartialEq for Error"],["impl StructuralPartialEq for Type"],["impl StructuralPartialEq for CoreBuiltin"],["impl StructuralPartialEq for Negate"],["impl StructuralPartialEq for Error"],["impl StructuralPartialEq for Direction"],["impl StructuralPartialEq for And"],["impl StructuralPartialEq for FFIBinding"],["impl StructuralPartialEq for Color"],["impl StructuralPartialEq for Location"],["impl StructuralPartialEq for New"],["impl StructuralPartialEq for BitwiseXor"],["impl StructuralPartialEq for Delete"],["impl StructuralPartialEq for CoreOp"],["impl StructuralPartialEq for StandardOp"],["impl StructuralPartialEq for Tag"],["impl StructuralPartialEq for StandardProgram"],["impl StructuralPartialEq for CoreProgram"],["impl StructuralPartialEq for BitwiseAnd"],["impl StructuralPartialEq for Output"],["impl StructuralPartialEq for Comparison"],["impl StructuralPartialEq for Pattern"],["impl StructuralPartialEq for Add"],["impl StructuralPartialEq for CoreProgram"],["impl StructuralPartialEq for StandardBuiltin"],["impl StructuralPartialEq for StandardProgram"],["impl StructuralPartialEq for Get"],["impl StructuralPartialEq for Annotation"],["impl StructuralPartialEq for Declaration"],["impl StructuralPartialEq for BitwiseNand"],["impl StructuralPartialEq for ConstExpr"],["impl StructuralPartialEq for OutputMode"],["impl StructuralPartialEq for Input"],["impl StructuralPartialEq for InputMode"],["impl StructuralPartialEq for SourceCodeLocation"],["impl StructuralPartialEq for StandardOp"],["impl StructuralPartialEq for Channel"],["impl StructuralPartialEq for Axis"],["impl StructuralPartialEq for Put"]] +"sage":[["impl StructuralPartialEq for Delete"],["impl StructuralPartialEq for Declaration"],["impl StructuralPartialEq for And"],["impl StructuralPartialEq for BitwiseNor"],["impl StructuralPartialEq for Add"],["impl StructuralPartialEq for BitwiseOr"],["impl StructuralPartialEq for Color"],["impl StructuralPartialEq for OutputMode"],["impl StructuralPartialEq for ConstExpr"],["impl StructuralPartialEq for Location"],["impl StructuralPartialEq for New"],["impl StructuralPartialEq for Direction"],["impl StructuralPartialEq for StandardOp"],["impl StructuralPartialEq for StandardProgram"],["impl StructuralPartialEq for InputMode"],["impl StructuralPartialEq for BitwiseNand"],["impl StructuralPartialEq for Get"],["impl StructuralPartialEq for BitwiseXor"],["impl StructuralPartialEq for CoreOp"],["impl StructuralPartialEq for CoreOp"],["impl StructuralPartialEq for Type"],["impl StructuralPartialEq for Negate"],["impl StructuralPartialEq for CoreProgram"],["impl StructuralPartialEq for Error"],["impl StructuralPartialEq for StandardProgram"],["impl StructuralPartialEq for Output"],["impl StructuralPartialEq for Input"],["impl StructuralPartialEq for Axis"],["impl StructuralPartialEq for Put"],["impl StructuralPartialEq for Annotation"],["impl StructuralPartialEq for StandardOp"],["impl StructuralPartialEq for Pattern"],["impl StructuralPartialEq for StandardBuiltin"],["impl StructuralPartialEq for Tag"],["impl StructuralPartialEq for BitwiseNot"],["impl StructuralPartialEq for FFIProcedure"],["impl StructuralPartialEq for FFIBinding"],["impl StructuralPartialEq for CoreProgram"],["impl StructuralPartialEq for Data"],["impl StructuralPartialEq for BitwiseAnd"],["impl StructuralPartialEq for CoreBuiltin"],["impl StructuralPartialEq for Channel"],["impl StructuralPartialEq for SourceCodeLocation"],["impl StructuralPartialEq for Comparison"],["impl StructuralPartialEq for Error"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/serde/de/trait.Deserialize.js b/docs/trait.impl/serde/de/trait.Deserialize.js index 3b2b614b..165e57e7 100644 --- a/docs/trait.impl/serde/de/trait.Deserialize.js +++ b/docs/trait.impl/serde/de/trait.Deserialize.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"sage":[["impl<'de> Deserialize<'de> for CoreBuiltin"],["impl<'de> Deserialize<'de> for Globals"],["impl<'de> Deserialize<'de> for StandardBuiltin"],["impl<'de> Deserialize<'de> for Axis"],["impl<'de> Deserialize<'de> for CoreOp"],["impl<'de> Deserialize<'de> for FFIProcedure"],["impl<'de> Deserialize<'de> for Location"],["impl<'de> Deserialize<'de> for StandardOp"],["impl<'de> Deserialize<'de> for Channel"],["impl<'de> Deserialize<'de> for InputMode"],["impl<'de> Deserialize<'de> for Mutability"],["impl<'de> Deserialize<'de> for Pattern"],["impl<'de> Deserialize<'de> for OutputMode"],["impl<'de> Deserialize<'de> for CoreProgram"],["impl<'de> Deserialize<'de> for Declaration"],["impl<'de> Deserialize<'de> for Output"],["impl<'de> Deserialize<'de> for Annotation"],["impl<'de> Deserialize<'de> for FFIBinding"],["impl<'de> Deserialize<'de> for PolyProcedure"],["impl<'de> Deserialize<'de> for Direction"],["impl<'de> Deserialize<'de> for Expr"],["impl<'de> Deserialize<'de> for Type"],["impl<'de> Deserialize<'de> for StandardProgram"],["impl<'de> Deserialize<'de> for SourceCodeLocation"],["impl<'de> Deserialize<'de> for ConstExpr"],["impl<'de> Deserialize<'de> for Input"],["impl<'de> Deserialize<'de> for Procedure"],["impl<'de> Deserialize<'de> for Color"]] +"sage":[["impl<'de> Deserialize<'de> for FFIBinding"],["impl<'de> Deserialize<'de> for Color"],["impl<'de> Deserialize<'de> for ConstExpr"],["impl<'de> Deserialize<'de> for Location"],["impl<'de> Deserialize<'de> for InputMode"],["impl<'de> Deserialize<'de> for Type"],["impl<'de> Deserialize<'de> for SourceCodeLocation"],["impl<'de> Deserialize<'de> for Declaration"],["impl<'de> Deserialize<'de> for Output"],["impl<'de> Deserialize<'de> for Mutability"],["impl<'de> Deserialize<'de> for Input"],["impl<'de> Deserialize<'de> for StandardBuiltin"],["impl<'de> Deserialize<'de> for StandardProgram"],["impl<'de> Deserialize<'de> for CoreOp"],["impl<'de> Deserialize<'de> for Pattern"],["impl<'de> Deserialize<'de> for OutputMode"],["impl<'de> Deserialize<'de> for CoreBuiltin"],["impl<'de> Deserialize<'de> for Channel"],["impl<'de> Deserialize<'de> for StandardOp"],["impl<'de> Deserialize<'de> for Procedure"],["impl<'de> Deserialize<'de> for Axis"],["impl<'de> Deserialize<'de> for Direction"],["impl<'de> Deserialize<'de> for PolyProcedure"],["impl<'de> Deserialize<'de> for CoreProgram"],["impl<'de> Deserialize<'de> for FFIProcedure"],["impl<'de> Deserialize<'de> for Globals"],["impl<'de> Deserialize<'de> for Annotation"],["impl<'de> Deserialize<'de> for Expr"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/trait.impl/serde/ser/trait.Serialize.js b/docs/trait.impl/serde/ser/trait.Serialize.js index 5e2cf9ef..c7383b93 100644 --- a/docs/trait.impl/serde/ser/trait.Serialize.js +++ b/docs/trait.impl/serde/ser/trait.Serialize.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"sage":[["impl Serialize for Mutability"],["impl Serialize for Annotation"],["impl Serialize for Location"],["impl Serialize for FFIBinding"],["impl Serialize for Expr"],["impl Serialize for FFIProcedure"],["impl Serialize for CoreBuiltin"],["impl Serialize for StandardProgram"],["impl Serialize for Color"],["impl Serialize for Procedure"],["impl Serialize for StandardOp"],["impl Serialize for Globals"],["impl Serialize for Declaration"],["impl Serialize for Type"],["impl Serialize for Direction"],["impl Serialize for CoreOp"],["impl Serialize for StandardBuiltin"],["impl Serialize for CoreProgram"],["impl Serialize for Axis"],["impl Serialize for Input"],["impl Serialize for ConstExpr"],["impl Serialize for InputMode"],["impl Serialize for Channel"],["impl Serialize for SourceCodeLocation"],["impl Serialize for OutputMode"],["impl Serialize for PolyProcedure"],["impl Serialize for Output"],["impl Serialize for Pattern"]] +"sage":[["impl Serialize for Type"],["impl Serialize for Mutability"],["impl Serialize for CoreBuiltin"],["impl Serialize for Annotation"],["impl Serialize for Expr"],["impl Serialize for SourceCodeLocation"],["impl Serialize for Declaration"],["impl Serialize for Color"],["impl Serialize for Direction"],["impl Serialize for PolyProcedure"],["impl Serialize for Input"],["impl Serialize for Channel"],["impl Serialize for CoreOp"],["impl Serialize for StandardBuiltin"],["impl Serialize for Location"],["impl Serialize for Pattern"],["impl Serialize for Globals"],["impl Serialize for CoreProgram"],["impl Serialize for Output"],["impl Serialize for InputMode"],["impl Serialize for Axis"],["impl Serialize for OutputMode"],["impl Serialize for FFIProcedure"],["impl Serialize for FFIBinding"],["impl Serialize for StandardProgram"],["impl Serialize for Procedure"],["impl Serialize for ConstExpr"],["impl Serialize for StandardOp"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/examples/frontend/array.sg b/examples/frontend/array.sg new file mode 100644 index 00000000..5a5abe45 --- /dev/null +++ b/examples/frontend/array.sg @@ -0,0 +1,52 @@ +fun main() { + let mut a = Array.new([1, 2, 3, 4, 5]); + a.println(); + a.set(1, 1000); + println(*a.get(1)); + a.println(); +} + +// An array with a constant parameter length +struct Array { + data: [T * N] +} + +impl Array { + // Create a new Array container + fun new(arr: [T * N]): Array { + return {data=arr}; + } + + // Get a value from the array + fun get(&self, n: Int): &T { + if n < N { + return &self.data[n]; + } else { + return Null; + } + } + + // Set a value in the array + fun set(&mut self, n: Int, val: T) { + self.data[n] = val; + } + + // Print the array + fun print(&self) { + print("["); + for let mut i=0; i { + Cons(T, &List), + Nil +} + +impl List { + fun make(value: T): List { + return List of Cons(value, new List of Nil); + } + + fun cons(List: List, value: T): List { + return List of Cons(value, new List); + } + + fun head(self: &List): T { + match self { + &of Cons(head, _) => head, + _ => panic(&"head of empty List") + } + } + + fun tail(self: &List): &List { + match self { + &of Cons(_, tail) => tail, + _ => panic(&"tail of empty List") + } + } + + fun print(self: &List) { + match self { + &of Cons(head, tail) => { + print(head); + print(" "); + tail.print(); + }, + _ => {} + } + } + + fun println(self: &List) { + self.print(); + println(" (special number=", N, ")"); + } + + fun map(self, f: fun(T) -> U): List { + match self { + of Cons(head, tail) => { + let map = tail.map(f); + map.cons(f(head)) + }, + _ => List of Nil + } + } +} + +const N = 555; +let l1 = List.make(1); +let l2 = List.make(2.0).cons(1.0); + +fun dub_int(n: Int): Int = n * 2; +fun dub_float(n: Float): Float = n * 2.0; + +l1.println(); +l2.println(); + +let l3 = l1.map(dub_int); +let l4 = l2.map(dub_float); +l3.println(); +l4.println(); \ No newline at end of file diff --git a/examples/frontend/const-generics-member.sg b/examples/frontend/const-generics-member.sg new file mode 100644 index 00000000..9c304e8d --- /dev/null +++ b/examples/frontend/const-generics-member.sg @@ -0,0 +1,37 @@ +fun test() { + println(X.0); +} + +fun test2() { + println(X); + println("x: ", X.x); + println("y: ", X.y); +} + +test<(5, 6)>(); +test2<{x=45, y=37}>(); + +type Test = {x: Int, y: Int}; +struct Point { + x: Int, + y: Int +} + +impl Point { + fun new(x: Int, y: Int): Point { + {x=x, y=y} + } + + fun move(&mut self, dx: Int, dy: Int) { + self.x += dx; + self.y += dy; + } +} + +fun test3() { + let mut p = P; + p.move(1, 1); + println(p) +} + +test3<{x=5, y=6}>(); \ No newline at end of file diff --git a/examples/frontend/matrix.sg b/examples/frontend/matrix.sg new file mode 100644 index 00000000..6ca1c127 --- /dev/null +++ b/examples/frontend/matrix.sg @@ -0,0 +1,114 @@ +struct Matrix { + arr: [[T * Cols] * Rows] +} + +impl Matrix { + fun new(x: T): Matrix { + return {arr=[[x] * Cols] * Rows}; + } + + fun get(&self, row: Int, col: Int): &T { + return &self.arr[row][col]; + } + + fun mul( + &self, + other: &Matrix, + zero: T, + add: fun(T, T) -> T, + mul: fun(T, T) -> T + ): Matrix { + let mut result = Matrix.new(zero); + for let mut j=0; j(&mut self, row: Int, col: Int) { + self.arr[row][col] = X; + } + + fun set_range(&mut self, row: Int) { + for let mut i=0; i(&mut self, row: Int) { + for let mut i=0; i(&mut self, col: Int) { + for let mut i=0; i(10); +let mut y = Matrix.new(5); +for let mut row=0; row < 4; row += 1; { + y.set_row<[1, 2, 3, 4]>(row); +} +y.set_range<4, [4, 3, 2, 1]>(0); + +x.set_col<[1, 2, 3, 4]>(0); +x.set<5>(1, 1); + +x.print(); +println(); +y.print(); +println(); + +fun add_ints(a: Int, b: Int): Int = a + b; +fun mul_ints(a: Int, b: Int): Int = a * b; + +let z = y.mul<4>(&x, 0, add_ints, mul_ints); +z.print(); + +struct Test { + a: Matrix, + b: Matrix, + c: Matrix +} + +impl Test { + fun new(): Test { + {a=Matrix.new(10), b=Matrix.new(5), c=Matrix.new(0)} + } + + fun test(&mut self) { + let b = self.b; + self.c = b.mul<1>(&self.a, 0, add_ints, mul_ints); + } +} + +let mut t = Test.new(); +for let mut i=0; i<1; i+=1; { + t.test(); +} +t.c.print(); \ No newline at end of file diff --git a/examples/frontend/matrix_point.sg b/examples/frontend/matrix_point.sg new file mode 100644 index 00000000..f239bc14 --- /dev/null +++ b/examples/frontend/matrix_point.sg @@ -0,0 +1,79 @@ +struct Matrix { + arr: [[T * Cols] * Rows] +} + +impl Matrix { + fun new(x: T): Matrix { + return {arr=[[x] * Cols] * Rows}; + } + + fun get(&self, row: Int, col: Int): &T { + return &self.arr[row][col]; + } + + fun mul( + &self, + other: &Matrix, + zero: T, + add: fun(T, T) -> T, + mul: fun(T, T) -> T + ): Matrix { + let mut result = Matrix.new(zero); + for let mut j=0; j(Point.new(1, 2)); +let mut y = Matrix.new(Point.new(-4, 5)); + +x.print(); +println(); +y.print(); +println(); + +let z = y.mul<4>(&x, Point.default(), Point.add, Point.mul); + +z.print(); +println(); \ No newline at end of file diff --git a/examples/frontend/typecheck-const-generics.sg b/examples/frontend/typecheck-const-generics.sg new file mode 100644 index 00000000..c72b3f36 --- /dev/null +++ b/examples/frontend/typecheck-const-generics.sg @@ -0,0 +1,113 @@ +struct Matrix { + arr: [[T * Cols] * Rows] +} + +impl Matrix { + fun new(x: T): Matrix { + return {arr=[[x] * Cols] * Rows}; + } + + fun get(&self, row: Int, col: Int): &T { + return &self.arr[row][col]; + } + + fun mul( + &self, + other: &Matrix, + zero: T, + add: fun(T, T) -> T, + mul: fun(T, T) -> T + ): Matrix { + let mut result = Matrix.new(zero); + for let mut j=0; j(&mut self, row: Int, col: Int) { + self.arr[row][col] = X; + } + + fun set_range(&mut self, row: Int) { + for let mut i=0; i(&mut self, row: Int) { + for let mut i=0; i(&mut self, col: Int) { + for let mut i=0; i(10); +let mut y = Matrix.new(5); +for let mut row=0; row < 4; row += 1; { + y.set_row<[1, 2, 3, 4]>(row); +} +y.set_range<4, [4, 3, 2, 1]>(0); + +x.set_col<[1, 2, 3, 4, 5]>(0); +x.set<5>(1, 1); + +x.print(); +println(); +y.print(); +println(); + +fun add_ints(a: Int, b: Int): Int = a + b; +fun mul_ints(a: Int, b: Int): Int = a * b; + +let z = y.mul<4>(&x, 0, add_ints, mul_ints); +z.print(); + +struct Test { + a: Matrix, + b: Matrix, + c: Matrix +} + +impl Test { + fun new(): Test { + {a=Matrix.new(10), b=Matrix.new(5), c=Matrix.new(0)} + } + + fun test(&mut self) { + let b = self.b; + self.c = b.mul<1>(&self.a, 0, add_ints, mul_ints); + } +} + +let mut t = Test.new(); +for let mut i=0; i<1; i+=1; { + t.test(); +} +t.c.print(); \ No newline at end of file diff --git a/examples/test-output/array.txt b/examples/test-output/array.txt new file mode 100644 index 00000000..7ecac042 --- /dev/null +++ b/examples/test-output/array.txt @@ -0,0 +1,3 @@ +[1, 2, 3, 4, 5] +1000 +[1, 1000, 3, 4, 5] diff --git a/examples/test-output/const-generics-enum.txt b/examples/test-output/const-generics-enum.txt new file mode 100644 index 00000000..c4d9ad8a --- /dev/null +++ b/examples/test-output/const-generics-enum.txt @@ -0,0 +1,4 @@ +1 (special number=999) +1.0 2.0 (special number=555) +2 (special number=999) +2.0 4.0 (special number=555) diff --git a/examples/test-output/const-generics-member.txt b/examples/test-output/const-generics-member.txt new file mode 100644 index 00000000..d49b1349 --- /dev/null +++ b/examples/test-output/const-generics-member.txt @@ -0,0 +1,5 @@ +5 +{x=45, y=37} +x: 45 +y: 37 +{x=6, y=7} diff --git a/examples/test-output/matrix.txt b/examples/test-output/matrix.txt new file mode 100644 index 00000000..183a72b4 --- /dev/null +++ b/examples/test-output/matrix.txt @@ -0,0 +1,24 @@ +1 10 10 10 +2 5 10 10 +3 10 10 10 +4 10 10 10 + +4 3 2 1 +1 2 3 4 +1 2 3 4 +1 2 3 4 + +20 85 100 100 +30 90 100 100 +30 90 100 100 +30 90 100 100 +500 +500 +500 +500 +500 +500 +500 +500 +500 +500 diff --git a/examples/test-output/matrix_point.txt b/examples/test-output/matrix_point.txt new file mode 100644 index 00000000..ebd27e76 --- /dev/null +++ b/examples/test-output/matrix_point.txt @@ -0,0 +1,15 @@ +{x=1, y=2} {x=1, y=2} {x=1, y=2} {x=1, y=2} +{x=1, y=2} {x=1, y=2} {x=1, y=2} {x=1, y=2} +{x=1, y=2} {x=1, y=2} {x=1, y=2} {x=1, y=2} +{x=1, y=2} {x=1, y=2} {x=1, y=2} {x=1, y=2} + +{x=-4, y=5} {x=-4, y=5} {x=-4, y=5} {x=-4, y=5} +{x=-4, y=5} {x=-4, y=5} {x=-4, y=5} {x=-4, y=5} +{x=-4, y=5} {x=-4, y=5} {x=-4, y=5} {x=-4, y=5} +{x=-4, y=5} {x=-4, y=5} {x=-4, y=5} {x=-4, y=5} + +{x=-16, y=40} {x=-16, y=40} {x=-16, y=40} {x=-16, y=40} +{x=-16, y=40} {x=-16, y=40} {x=-16, y=40} {x=-16, y=40} +{x=-16, y=40} {x=-16, y=40} {x=-16, y=40} {x=-16, y=40} +{x=-16, y=40} {x=-16, y=40} {x=-16, y=40} {x=-16, y=40} + diff --git a/examples/test-output/typecheck-const-generics.error.txt b/examples/test-output/typecheck-const-generics.error.txt new file mode 100644 index 00000000..331eb684 --- /dev/null +++ b/examples/test-output/typecheck-const-generics.error.txt @@ -0,0 +1 @@ +mismatched types: expected [Int * 4], found const param [1, 2, 3, 4, 5] in ((X: [Int * 4]) => (&mut (Matrix), Int) -> None) \ No newline at end of file diff --git a/examples/web/index.html b/examples/web/index.html index eb344948..de6ab312 100644 --- a/examples/web/index.html +++ b/examples/web/index.html @@ -85,6 +85,138 @@ } console.log(document.getElementById("example").value); switch (document.getElementById("example").value) { + case "const-generics": + source.setValue(`fun main() { + // Create an array struct + let mut a = Array.new([1, 2, 3, 4, 5]); + // Print it out + a.println(); + // Set a value! + a.set(1, 1000); + // Print the changed value + println(*a.get(1)); + // Print the whole changed array + a.println(); +} + +// An array with a constant parameter length +struct Array { + data: [T * N] +} + +impl Array { + // Create a new Array container + fun new(arr: [T * N]): Array { + return {data=arr}; + } + + // Get a value from the array + fun get(&self, n: Int): &T { + if n < N { + return &self.data[n]; + } else { + return Null; + } + } + + // Set a value in the array + fun set(&mut self, n: Int, val: T) { + self.data[n] = val; + } + + // Print the array + fun print(&self) { + print("["); + for let mut i=0; i(10); // Populate with 10 + let y = Matrix.new(5); // Populate with 5 + + // Print the two matrices + x.print(); + y.print(); + + // Provide the matrix with the operations for the elem type + fun add_ints(a: Int, b: Int): Int = a + b; + fun mul_ints(a: Int, b: Int): Int = a * b; + + // Perform the mat mul! + let z = y.mul<4>(&x, 0, add_ints, mul_ints); + // Print the result + z.print(); +} + +// Define a constant sized matrix with a generic element type +// and parameterized width and height. +struct Matrix { + arr: [[T * Cols] * Rows] +} + +// Add some methods to our matrix +impl Matrix { + // Create a new matrix populated with initial values + fun new(x: T): Matrix { + return {arr=[[x] * Cols] * Rows}; + } + + // Get a value from a matrix + fun get(&self, row: Int, col: Int): &T { + return &self.arr[row][col]; + } + + // Multiply with another matrix + fun mul( + &self, + other: &Matrix, + zero: T, + add: fun(T, T) -> T, + mul: fun(T, T) -> T + ): Matrix { + let mut result = Matrix.new(zero); + for let mut j=0; j { + source.setValue(`fun main() { + let x = Option of Some(5); + println(x.unwrap()); +} + +enum Option { Some(T), Nothing, } @@ -1830,11 +1967,6 @@ } } -fun main() { - let x = Option of Some(5); - println(Option.unwrap(x)); -} - main();`) break; default: @@ -1899,7 +2031,9 @@ + + diff --git a/src/frontend/parse.rs b/src/frontend/parse.rs index f5108113..8dfd9ae8 100644 --- a/src/frontend/parse.rs +++ b/src/frontend/parse.rs @@ -277,14 +277,6 @@ fn make_env() -> sage_lisp::Env { Expr::None }); - // env.bind_builtin("do", |env, exprs| { - // let mut result = Expr::default(); - // for e in exprs { - // result = env.eval(e.clone()); - // } - // result - // }); - env.bind_lazy_builtin("do", |_env, exprs| Expr::Many(Vec::from(exprs))); env.bind_builtin("sqrt", |env, expr| { @@ -1365,10 +1357,6 @@ fn parse_attribute<'a, E: ParseError<&'a str> + ContextError<&'a str>>( fn parse_impl_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( input: &'a str, ) -> IResult<&'a str, Statement, E> { - // "impl" ":")?> )>> => { - // let args: Vec<_> = args.into_iter().map(|(_name, ty)| ty).collect(); - // Statement::Declaration(Declaration::Impl(name, args, body)) - // }, let (input, _) = tag("impl")(input)?; let (input, ty) = cut(parse_type)(input)?; @@ -1397,7 +1385,6 @@ fn parse_impl_item<'a, E: ParseError<&'a str> + ContextError<&'a str>>( input: &'a str, ty: &Type, ) -> IResult<&'a str, (String, ConstExpr), E> { - // let (input, _) = whitespace(input)?; if let Ok((input, method)) = parse_impl_method::(input, ty) { return Ok((input, method)); } @@ -1422,14 +1409,6 @@ fn parse_impl_fun<'a, E: ParseError<&'a str> + ContextError<&'a str>>( let (input, (params, ret)) = cut(parse_fun_params)(input)?; let (input, _) = whitespace(input)?; let (input, body) = cut(parse_block)(input)?; - // Ok((input, (name.to_owned(), ConstExpr::Proc(Procedure::new(name, params, ret, body)))) - - // lazy_static! { - // static ref IMPL_FUN_COUNTER: RwLock = RwLock::new(0); - // } - // let mut count = *IMPL_FUN_COUNTER.read().unwrap(); - // count += 1; - // *IMPL_FUN_COUNTER.write().unwrap() = count; if let Some(args) = template_args { Ok(( @@ -1477,10 +1456,6 @@ fn parse_impl_method<'a, E: ParseError<&'a str> + ContextError<&'a str>>( input: &'a str, ty: &Type, ) -> IResult<&'a str, (String, ConstExpr), E> { - // "fun" ":")?> )>> ":" => { - // let args: Vec<_> = args.into_iter().map(|(_name, ty)| ty).collect(); - // Statement::Declaration(Declaration::Proc(name.clone(), Procedure::new(name, args, ret, body))) - // }, trace!("Parsing impl method"); let (input, _) = tag("fun")(input)?; trace!("Parsing method"); @@ -1493,33 +1468,61 @@ fn parse_impl_method<'a, E: ParseError<&'a str> + ContextError<&'a str>>( let (input, template_args) = cut(opt(parse_type_params))(input)?; trace!("Parsed template args: {template_args:#?}"); // Get the function parameters with mutability - let (input, (params, ret)) = parse_method_params(input, ty)?; - trace!("Parsed method parameters: {params:#?}, {ret:#?}"); - let (input, _) = whitespace(input)?; - let (input, body) = cut(parse_block)(input)?; - // Ok((input, Statement::Declaration(Declaration::Proc(name.to_owned(), Procedure::new(Some(name.to_owned()), params, ret, body)))) - if let Some(args) = template_args { - Ok(( - input, - ( - name.to_owned(), - ConstExpr::PolyProc(PolyProcedure::new( + if let Ok((input, (params, ret))) = parse_method_params::(input, ty) { + trace!("Parsed method parameters: {params:#?}, {ret:#?}"); + let (input, _) = whitespace(input)?; + let (input, body) = cut(parse_block)(input)?; + if let Some(args) = template_args { + Ok(( + input, + ( name.to_owned(), - args.into_iter().map(|x| x.to_owned()).collect(), - params, - ret, - body, - )), - ), - )) + ConstExpr::PolyProc(PolyProcedure::new( + name.to_owned(), + args.into_iter().map(|x| x.to_owned()).collect(), + params, + ret, + body, + )), + ), + )) + } else { + Ok(( + input, + ( + name.to_owned(), + ConstExpr::Proc(Procedure::new(Some(name.to_owned()), params, ret, body)), + ), + )) + } } else { - Ok(( - input, - ( - name.to_owned(), - ConstExpr::Proc(Procedure::new(Some(name.to_owned()), params, ret, body)), - ), - )) + let (input, (params, ret)) = parse_fun_params(input)?; + trace!("Parsed method parameters: {params:#?}, {ret:#?}"); + let (input, _) = whitespace(input)?; + let (input, body) = cut(parse_block)(input)?; + if let Some(args) = template_args { + Ok(( + input, + ( + name.to_owned(), + ConstExpr::PolyProc(PolyProcedure::new( + name.to_owned(), + args.into_iter().map(|x| x.to_owned()).collect(), + params, + ret, + body, + )), + ), + )) + } else { + Ok(( + input, + ( + name.to_owned(), + ConstExpr::Proc(Procedure::new(Some(name.to_owned()), params, ret, body)), + ), + )) + } } } @@ -1558,9 +1561,6 @@ fn parse_match_expr<'a, E: ParseError<&'a str> + ContextError<&'a str>>( branches.push((pat, body)); } - // trace!("Parsed branches: {input}"); - // trace!("Parsed branches: {branches:#?}"); - let (input, _) = whitespace(input)?; let (input, _) = tag("}")(input)?; Ok((input, Expr::Match(expr.into(), branches))) @@ -1626,7 +1626,6 @@ fn parse_pattern_atom<'a, E: ParseError<&'a str> + ContextError<&'a str>>( context("tuple", parse_tuple_pattern), context("group", delimited(tag("("), cut(parse_pattern), tag(")"))), context("const", map(parse_const, Pattern::ConstExpr)), - // context("tuple", map(ma ))(input)?; Ok((input, pattern)) } @@ -1836,7 +1835,7 @@ fn parse_import_decl<'a, E: ParseError<&'a str> + ContextError<&'a str>>( // Optionally parse an alias let (input, alias) = opt(preceded(whitespace, preceded(tag("as"), cut(parse_symbol))))(input)?; - // let alias = alias.map(|x| x.to_owned()); + // If there's a comma, continue parsing let (input, _) = whitespace(input)?; @@ -1851,16 +1850,6 @@ fn parse_import_decl<'a, E: ParseError<&'a str> + ContextError<&'a str>>( .map(|(x, y)| (x.to_owned(), y.map(|z| z.to_owned()))) .collect(); - // let mut decls = vec![]; - // for (name, alias) in &imports { - // // decls.push(Declaration::Const(alias.clone(), ConstExpr::var(module_name).field(ConstExpr::var(name)))); - // decls.push(Declaration::FromImport { - // module: , - // name: name.clone(), - // alias: alias.map(|x| x.to_owned()), - // }); - // } - let (input, _) = whitespace(input)?; let (input, _) = tag(";")(input)?; @@ -1975,7 +1964,6 @@ fn parse_decl<'a, E: ParseError<&'a str> + ContextError<&'a str>>( fn parse_if_expr<'a, E: ParseError<&'a str> + ContextError<&'a str>>( input: &'a str, ) -> IResult<&'a str, Expr, E> { - // "if" > => Expr::If(condition, Box::new(then), else.map(Box::new)), let (input, _) = tag("if")(input)?; let (input, _) = whitespace(input)?; let (input, condition) = cut(parse_expr)(input)?; @@ -2026,7 +2014,6 @@ fn parse_if_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( fn parse_if_let_expr<'a, E: ParseError<&'a str> + ContextError<&'a str>>( input: &'a str, ) -> IResult<&'a str, Expr, E> { - // "if" > => Expr::If(condition, Box::new(then), else.map(Box::new)), let (input, _) = tag("if")(input)?; let (input, _) = whitespace(input)?; let (input, _) = tag("let")(input)?; @@ -2082,7 +2069,6 @@ fn parse_when_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( fn parse_while_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( input: &'a str, ) -> IResult<&'a str, Statement, E> { - // "while" => Statement::While(condition, Box::new(body)), let (input, _) = tag("while")(input)?; let (input, _) = whitespace(input)?; let (input, condition) = cut(parse_expr)(input)?; @@ -2097,7 +2083,6 @@ fn parse_while_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( fn parse_for_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( input: &'a str, ) -> IResult<&'a str, Statement, E> { - // "for" > > > => Statement::For(init.map(Box::new), condition.map(Box::new), step.map(Box::new), Box::new(body)), let (input, _) = tag("for")(input)?; let (input, _) = whitespace(input)?; let (input, init) = cut(parse_short_stmt)(input)?; @@ -2109,7 +2094,7 @@ fn parse_for_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( let (input, step) = cut(parse_short_stmt)(input)?; let (input, _) = whitespace(input)?; let (input, body) = cut(parse_block)(input)?; - // Ok((input, Statement::Expr(Expr::For(init.map(Box::new), condition.map(Box::new), step.map(Box::new), Box::new(body))))) + let mut init_expr = Expr::NONE; let mut init_decl = Declaration::many(vec![]); match init { @@ -2137,10 +2122,6 @@ fn parse_for_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( fn parse_fun_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( input: &'a str, ) -> IResult<&'a str, Statement, E> { - // "fun" ":")?> )>> ":" => { - // let args: Vec<_> = args.into_iter().map(|(_name, ty)| ty).collect(); - // Statement::Declaration(Declaration::Proc(name.clone(), Procedure::new(name, args, ret, body))) - // }, let (input, _) = tag("fun")(input)?; trace!("Parsing function"); let (input, _) = whitespace(input)?; @@ -2156,7 +2137,6 @@ fn parse_fun_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( let (input, _) = whitespace(input)?; let (input, body) = parse_block(input)?; trace!("Parsed function body: {body}"); - // Ok((input, Statement::Declaration(Declaration::Proc(name.to_owned(), Procedure::new(Some(name.to_owned()), params, ret, body))))) if let Some(args) = template_args { Ok(( input, @@ -2191,10 +2171,6 @@ fn parse_fun_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( fn parse_quick_fun_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( input: &'a str, ) -> IResult<&'a str, Statement, E> { - // "fun" ":")?> )>> ":" => { - // let args: Vec<_> = args.into_iter().map(|(_name, ty)| ty).collect(); - // Statement::Declaration(Declaration::Proc(name.clone(), Procedure::new(name, args, ret, body))) - // }, let (input, _) = tag("fun")(input)?; trace!("Parsing function"); let (input, _) = whitespace(input)?; @@ -2214,7 +2190,7 @@ fn parse_quick_fun_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( let (input, _) = whitespace(input)?; let (input, _) = cut(tag(";"))(input)?; trace!("Parsed function body: {body}"); - // Ok((input, Statement::Declaration(Declaration::Proc(name.to_owned(), Procedure::new(Some(name.to_owned()), params, ret, body))))) + if let Some(args) = template_args { Ok(( input, @@ -2267,7 +2243,6 @@ fn parse_fun_params<'a, E: ParseError<&'a str> + ContextError<&'a str>>( let (input, _) = whitespace(input)?; let (input, last) = opt(pair( - // parse_symbol, pair( map(opt(tag("mut")), |x| match x { Some(_) => Mutability::Mutable, @@ -2617,7 +2592,7 @@ fn parse_struct_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( Declaration::Type( name.to_owned(), Type::Poly( - params.into_iter().map(|x| x.to_owned()).collect(), + params, Type::Struct(fields).into(), ), ), @@ -2678,7 +2653,7 @@ fn parse_enum_stmt<'a, E: ParseError<&'a str> + ContextError<&'a str>>( Declaration::Type( name.to_owned(), Type::Poly( - params.into_iter().map(|x| x.to_owned()).collect(), + params, Type::EnumUnion(fields).into(), ), ), @@ -2949,12 +2924,19 @@ fn parse_type_enum<'a, E: ParseError<&'a str> + ContextError<&'a str>>( fn parse_type_params<'a, E: ParseError<&'a str> + ContextError<&'a str>>( input: &'a str, -) -> IResult<&'a str, Vec, E> { +) -> IResult<&'a str, Vec<(String, Option)>, E> { let (input, _) = tag("<")(input)?; let (input, _) = whitespace(input)?; - let (input, mut params) = many0(terminated(parse_symbol, tag(",")))(input)?; + let (input, mut params) = many0(terminated(alt(( + preceded(delimited(whitespace, tag("const"), whitespace), map(pair(parse_symbol, delimited(terminated(whitespace, tag(":")), parse_type, whitespace)), |(name, ty)| (name, Some(ty)))), + map(parse_symbol, |x| (x, None)) + )), preceded(whitespace, tag(","))))(input)?; let (input, _) = whitespace(input)?; - let (input, last_param) = opt(parse_symbol)(input)?; + let (input, last_param) = opt(alt(( + preceded(delimited(whitespace, tag("const"), whitespace), map(pair(parse_symbol, delimited(terminated(whitespace, tag(":")), parse_type, whitespace)), |(name, ty)| (name, Some(ty)))), + // map(pair(parse_symbol, delimited(terminated(whitespace, tag(":")), parse_type, whitespace)), |(name, ty)| (name, Some(ty))), + map(parse_symbol, |x| (x, None)) + )))(input)?; let (input, _) = whitespace(input)?; let (input, _) = tag(">")(input)?; @@ -2962,7 +2944,7 @@ fn parse_type_params<'a, E: ParseError<&'a str> + ContextError<&'a str>>( params.push(last_param); } - Ok((input, params.into_iter().map(|x| x.to_string()).collect())) + Ok((input, params.into_iter().map(|(name, ty)| (name.to_string(), ty)).collect())) } fn parse_type_function<'a, E: ParseError<&'a str> + ContextError<&'a str>>( @@ -3005,19 +2987,23 @@ fn parse_type_apply<'a, E: ParseError<&'a str> + ContextError<&'a str>>( ) -> IResult<&'a str, Type, E> { let (input, ty) = parse_type_atom(input)?; let (input, _) = whitespace(input)?; - let (input, _) = tag("<")(input)?; - let (input, _) = whitespace(input)?; - let (input, mut args) = many0(terminated(parse_type, tag(",")))(input)?; - let (input, _) = whitespace(input)?; - let (input, last_arg) = opt(parse_type)(input)?; - let (input, _) = whitespace(input)?; - let (input, _) = tag(">")(input)?; - if let Some(last_arg) = last_arg { - args.push(last_arg); + if let Ok((input, _)) = tag::<&str, &str, E>("<")(input) { + let (input, _) = whitespace(input)?; + let (input, mut args) = many0(terminated(parse_type, tag(",")))(input)?; + let (input, _) = whitespace(input)?; + let (input, last_arg) = opt(parse_type)(input)?; + let (input, _) = whitespace(input)?; + let (input, _) = tag(">")(input)?; + + if let Some(last_arg) = last_arg { + args.push(last_arg); + } + + Ok((input, Type::Apply(Box::new(ty), args))) + } else { + return Ok((input, ty)) } - - Ok((input, Type::Apply(Box::new(ty), args))) } fn parse_type_primitive<'a, E: ParseError<&'a str> + ContextError<&'a str>>( @@ -3053,6 +3039,7 @@ fn parse_type_atom<'a, E: ParseError<&'a str> + ContextError<&'a str>>( parse_type_function, map(parse_symbol, |x| Type::Symbol(x.to_string())), parse_type_group, + map(parse_const_atom, |x| Type::ConstParam(x.into())) ))(input)?; Ok((input, ty)) @@ -3526,19 +3513,22 @@ fn parse_const_monomorph<'a, E: ParseError<&'a str> + ContextError<&'a str>>( ) -> IResult<&'a str, ConstExpr, E> { let (input, expr) = parse_const_term(input)?; let (input, _) = whitespace(input)?; - let (input, _) = tag("<")(input)?; - let (input, _) = whitespace(input)?; - let (input, mut tys) = many0(terminated(parse_type, tag(",")))(input)?; - let (input, _) = whitespace(input)?; - let (input, last_ty) = opt(parse_type)(input)?; - let (input, _) = whitespace(input)?; - let (input, _) = tag(">")(input)?; - - if let Some(last_ty) = last_ty { - tys.push(last_ty); + if let Ok((input, _)) = tag::<&str, &str, E>("<")(input) { + let (input, _) = whitespace(input)?; + let (input, mut tys) = many0(terminated(parse_type, tag(",")))(input)?; + let (input, _) = whitespace(input)?; + let (input, last_ty) = opt(parse_type)(input)?; + let (input, _) = whitespace(input)?; + let (input, _) = tag(">")(input)?; + + if let Some(last_ty) = last_ty { + tys.push(last_ty); + } + + Ok((input, expr.monomorphize(tys))) + } else { + Ok((input, expr)) } - - Ok((input, expr.monomorphize(tys))) } fn parse_const_variant<'a, E: ParseError<&'a str> + ContextError<&'a str>>( @@ -3605,6 +3595,7 @@ fn parse_const_atom<'a, E: ParseError<&'a str> + ContextError<&'a str>>( parse_const_sizeof_expr, parse_const_sizeof_type, parse_const_tuple, + parse_const_group, parse_const_bool, parse_const_null, parse_const_none, @@ -3622,7 +3613,6 @@ fn parse_const_atom<'a, E: ParseError<&'a str> + ContextError<&'a str>>( }), parse_const_array, parse_const_struct, - parse_const_group, map(parse_symbol, |x| ConstExpr::Symbol(x.to_string())), ))(input) } @@ -4095,7 +4085,7 @@ mod tests { fn compile_and_run(code: &str, input: &str) -> Result { let _ = rayon::ThreadPoolBuilder::new() .num_threads(16) - .stack_size(2048 * 1024 * 1024) + .stack_size(512 * 1024 * 1024) .build_global(); // Compiling most examples overflows the tiny stack for tests. // So, we spawn a new thread with a larger stack size. @@ -4468,7 +4458,7 @@ mod tests { assert_parse_type( "fun(Option) -> Bool", Some(Type::Poly( - vec!["T".to_string()], + vec![("T".to_string(), None)], Type::Proc( vec![Type::Apply( Box::new(Type::Symbol("Option".to_string())), @@ -4483,7 +4473,7 @@ mod tests { assert_parse_type( "fun(Option, Int) -> Bool", Some(Type::Poly( - vec!["T".to_string()], + vec![("T".to_string(), None)], Type::Proc( vec![ Type::Apply( @@ -4871,52 +4861,5 @@ p(5); ); trace!("Parsing block"); - // trace!("{:#?}", parse_suite::>(0, r#" - // enum Result: - // Ok(T) - // Err(E) - - // struct Point: - // x: Int - // y: Int - - // if True and 1 > 2 + 3: - // println(a + b) - // a - b - // while not a: - // println("Testing") - // std.println(5) - // increment(&mut a) - - // Result of Ok(5) - - // "#)); - - // impl Result: - // def unwrap(self) -> T: - // match self: - // of Ok(x) => x - // of Err(e) => panic(e) } - - // #[test] - // fn test_parse_const_tuple() { - // let input = "(a = 1, b = 2)"; - // let result = parse_const_tuple(input); - // assert_eq!(result, Ok(("", ConstExpr::Tuple(vec![ConstExpr::Tuple(vec![ConstExpr::Symbol("a".to_string()), ConstExpr::Int(1)]), ConstExpr::Tuple(vec![ConstExpr::Symbol("b".to_string()), ConstExpr::Int(2)])])))); - // } - - // #[test] - // fn test_parse_const_array() { - // let input = "[1, 2, 3]"; - // let result = parse_const_array(input); - // assert_eq!(result, Ok(("", ConstExpr::Array(vec![ConstExpr::Int(1), ConstExpr::Int(2), ConstExpr::Int(3)]))); - // } - - // #[test] - // fn test_parse_const_struct() { - // let input = "struct {a = 1, b = 2}"; - // let result = parse_const_struct(input); - // assert_eq!(result, Ok(("", ConstExpr::Struct(vec![("a".to_string(), ConstExpr::Int(1)), ("b".to_string(), ConstExpr::Int(2))].into_iter().collect()))); - // } } diff --git a/src/lir/compile.rs b/src/lir/compile.rs index f2e0d120..eded37b6 100644 --- a/src/lir/compile.rs +++ b/src/lir/compile.rs @@ -548,7 +548,7 @@ impl Compile for Expr { Self::EnumUnion(t, variant, val) => { // Get the size of the tagged union. let result_size = t.get_size(env)?; - let t = t.simplify_until_concrete(env)?; + let t = t.simplify_until_concrete(env, false)?; if let Type::EnumUnion(fields) = t { // Get the list of possible variant names. let variants = fields.clone().into_keys().collect::>(); @@ -843,7 +843,7 @@ impl Compile for Expr { // val_type.add_monomorphized_associated_consts(env)?; // Push the address of the struct, tuple, or union onto the stack. - match val_type.simplify_until_has_members(env)? { + match val_type.simplify_until_has_members(env, false)? { // If the value is a struct, tuple, or union: Type::Struct(_) | Type::Tuple(_) | Type::Union(_) => { // Compile a reference to the inner value with the expected mutability. @@ -928,7 +928,7 @@ impl Compile for Expr { // val_type.add_monomorphized_associated_consts(env)?; // Push the address of the struct, tuple, or union onto the stack. - match val_type.simplify_until_has_members(env)? { + match val_type.simplify_until_has_members(env, false)? { // If the value is a struct, tuple, or union: Type::Struct(_) | Type::Tuple(_) | Type::Union(_) => { // Compile a reference to the inner value with the expected mutability. @@ -1071,13 +1071,19 @@ impl Compile for ConstExpr { let ty = self.get_type(env)?; // Compile the constant expression. match self { - Self::Template(_, _) => { + Self::Any + | Self::Template(_, _) => { // Cannot compile a template expression. return Err(Error::UnsizedType(ty)); } - Self::Type(_) => { - // Do nothing. + Self::Type(t) => { + if t.is_const_param() { + let cexpr = t.simplify_until_const_param(env, false)?; + cexpr.compile_expr(env, output)? + } else { + return Err(Error::UnsizedType(ty)); + } } Self::Member(container, member) => { let new_container = *container.clone(); @@ -1097,6 +1103,9 @@ impl Compile for ConstExpr { } fields[&name].clone().compile_expr(env, output)? } + (Self::Type(ty), member) if ty.is_const_param() => { + ty.simplify_until_const_param(env, false)?.field(member).compile_expr(env, output)? + } (Self::Type(ty), Self::Symbol(name)) => { if let Some((constant, _)) = env.get_associated_const(&ty, &name) { debug!("Compiling associated constant {constant} in environment {env}"); @@ -1108,7 +1117,7 @@ impl Compile for ConstExpr { } (Self::Declare(bindings, expr), field) => { let mut new_env = env.clone(); - new_env.add_declaration(&bindings)?; + new_env.add_declaration(&bindings, true)?; expr.field(field).compile_expr(&mut new_env, output)?; } (a, b) => { @@ -1128,7 +1137,7 @@ impl Compile for ConstExpr { Self::Declare(bindings, body) => { debug!("Compiling declaration {bindings} with body {body} in environment {env}"); let mut new_env = env.clone(); - new_env.add_declaration(&bindings)?; + new_env.add_declaration(&bindings, true)?; body.compile_expr(&mut new_env, output)?; } Self::Monomorphize(expr, ty_args) => match expr.eval(env)? { @@ -1164,7 +1173,7 @@ impl Compile for ConstExpr { } let mut result = *result.clone(); - for (param, ty_arg) in params.into_iter().zip(ty_args) { + for ((param, _), ty_arg) in params.into_iter().zip(ty_args) { result.substitute(¶m, &ty_arg); } result = result.eval(env)?; @@ -1174,7 +1183,7 @@ impl Compile for ConstExpr { } Self::Declare(bindings, expr) => { let mut new_env = env.clone(); - new_env.add_declaration(&bindings)?; + new_env.add_declaration(&bindings, true)?; expr.monomorphize(ty_args) .compile_expr(&mut new_env, output)?; } @@ -1385,7 +1394,7 @@ impl Compile for ConstExpr { Self::EnumUnion(t, variant, val) => { // Get the size of the tagged union. let result_size = t.get_size(env)?; - let t = t.simplify_until_has_variants(env)?; + let t = t.simplify_until_has_variants(env, false)?; // Get the inner list of variants and compile the expression using this information. if let Type::EnumUnion(variants) = t.clone().simplify(env)? { @@ -1459,7 +1468,7 @@ impl Compile for ConstExpr { Self::Of(enum_type, variant) => { // Only try to simplify the type 50 times at most. // This is to prevent infinite loops and to keep recursion under control. - match enum_type.simplify_until_has_variants(env)? { + match enum_type.simplify_until_has_variants(env, false)? { // If the type is an enum, we can continue. Type::Enum(variants) => { // Get the index of the variant. diff --git a/src/lir/env.rs b/src/lir/env.rs index ce432697..f120fcf4 100644 --- a/src/lir/env.rs +++ b/src/lir/env.rs @@ -253,10 +253,13 @@ impl Env { for (other_ty, consts) in associated_constants.iter() { if matches!(ty.is_monomorph_of(other_ty, self), Ok(true)) { debug!("Type {ty} is monomorph of {other_ty}"); + for (name, (constant, ty)) in consts { + debug!(" {name}: {ty} = {constant}") + } let template = other_ty.clone(); let ty_params = template.get_template_params(self); - let ty_param_set = ty_params.clone().into_iter().collect::>(); + let ty_param_set = ty_params.clone().into_iter().map(|x| x.0).collect::>(); let monomorph = ty.clone(); debug!("Monomorph of {template} is {monomorph}"); let mut symbols = HashMap::new(); @@ -272,12 +275,12 @@ impl Env { debug!("Failed to get monomorph template args for {monomorph} of {template}"); continue; } - for (symbol, ty) in &symbols { - debug!("----> {symbol} == {ty}"); + for (symbol, (ty, specifier)) in &symbols { + debug!("----> {symbol} == {ty}: {specifier:?}"); } let template_associated_consts = consts.clone(); let mut ty_args = Vec::new(); - for ty_param in &ty_params { + for (ty_param, _) in &ty_params { if let Some(arg) = symbols.get(ty_param) { ty_args.push(arg.clone()); } else { @@ -286,8 +289,8 @@ impl Env { } if ty_args.len() != ty_params.len() { - debug!("Mismatched number of template arguments for {monomorph} of {template}"); - debug!("Expected {ty_params:?}, found {ty_args:?}"); + error!("Mismatched number of template arguments for {monomorph} of {template}"); + error!("Expected {ty_params:?}, found {ty_args:?}"); continue; } @@ -298,10 +301,9 @@ impl Env { if let Some((_, const_ty)) = template_associated_consts.get(name) { debug!("Found cached associated const (type) {name} of type {const_ty}"); - // let result = const_ty.apply(ty_args.clone()).simplify_until_simple(self).ok()?; - // let result = const_ty.apply(ty_args.clone()); - let result = const_ty.apply(ty_args.clone()); - match result.simplify_until_simple(self) { + + let result = const_ty.apply(ty_args.clone().into_iter().map(|x|x.0).collect()); + match result.simplify_until_simple(self, false) { Ok(result) => { debug!("Found associated const (type) {name} of type {ty} = {result}"); return Some(result); @@ -309,24 +311,23 @@ impl Env { Err(_err) => { debug!("Found associated const (type) {name} of type {ty} = {result} (failed to simplify)"); return Some(result); - // debug!("Failed to simplify associated const (type) {name} of type {ty} = {result}"); - // debug!("Error: {err}"); - // continue; } } - // info!("Found associated const (type) {name} of type {ty} = {result}"); - // return Some(result); } debug!("Could not find associated const {name} of type {ty} in {template}"); for template_const_name in template_associated_consts.keys() { debug!(" {template_const_name} != {name}"); } + } else { + debug!("Type {ty} is not monomorph of {other_ty}"); } if !ty.can_decay_to(other_ty, self).unwrap_or(false) { - trace!("Type {other_ty} does not equal {ty}"); + debug!("Type {other_ty} does not equal {ty}"); continue; + } else { + debug!("Type {other_ty} equals {ty}"); } if let Some((constant, expr_ty)) = consts.get(name) { let constant = constant.clone(); @@ -337,7 +338,6 @@ impl Env { return Some(expr_ty); } } - trace!("Could not find associated const {name} of type {ty} in {self}"); drop(associated_constants); if let Type::Type(inner_ty) = ty { @@ -355,11 +355,12 @@ impl Env { return Some(ty); } } + error!("Could not find associated const {name} of type {ty} in {self}"); None } pub fn get_associated_const(&self, ty: &Type, name: &str) -> Option<(ConstExpr, Type)> { - trace!( + debug!( "Getting associated const {name} of type {ty} in {self} with types {:?}", self.types ); @@ -381,7 +382,7 @@ impl Env { let monomorph = ty.clone(); let mut symbols = HashMap::new(); let ty_params = template.get_template_params(self); - let ty_param_set = ty_params.clone().into_iter().collect::>(); + let ty_param_set = ty_params.clone().into_iter().map(|x| x.0).collect::>(); if monomorph .get_monomorph_template_args( &template.strip_template(self), @@ -394,16 +395,16 @@ impl Env { debug!("Failed to get monomorph template args for {monomorph} of {template}"); continue; } - for (symbol, ty) in &symbols { - debug!("----> {symbol} == {ty}"); + for (symbol, (ty, expected)) in &symbols { + debug!("----> {symbol} == {ty}, {expected:?}"); } let template_associated_consts = consts.clone(); let mut ty_args = Vec::new(); - for ty_param in &ty_params { - if let Some(arg) = symbols.get(ty_param) { + for (ty_param, _) in &ty_params { + if let Some((arg, _)) = symbols.get(ty_param) { ty_args.push(arg.clone()); } else { - continue; + debug!("Could not find symbol {ty_param}"); } } @@ -416,7 +417,7 @@ impl Env { if let Some((const_expr, const_ty)) = template_associated_consts.get(name) { debug!("Found cached associated const pair: {const_expr} with type {const_ty}"); let mut result_ty = const_ty.apply(ty_args.clone()); - result_ty = match result_ty.simplify_until_simple(self) { + result_ty = match result_ty.simplify_until_simple(self, true) { Ok(result) => { debug!("Found associated const {name} of type {ty} = {result}"); result @@ -436,7 +437,7 @@ impl Env { debug!("Could not find associated const {name} of type {ty} in {template}"); // return self.get_associated_const(&monomorph, name); } else { - // info!("Type {ty} is not monomorph of {other_ty}"); + debug!("Type {ty} is not monomorph of {other_ty}"); } if !ty.can_decay_to(other_ty, self).unwrap_or(false) { @@ -573,7 +574,7 @@ impl Env { ) -> Result<(), Error> { debug!("Adding monomorphized associated constants of type {template} to {monomorph} with type arguments {ty_args:?} to environment"); - let monomorph = if let Ok(simplified) = monomorph.simplify_until_simple(self) { + let monomorph = if let Ok(simplified) = monomorph.simplify_until_simple(self, false) { debug!("Simplified {monomorph} to {simplified}"); simplified } else { @@ -640,7 +641,7 @@ impl Env { // Strip off the template parameters from the type arguments. let mono_const = if let ConstExpr::Template(ty_params, cexpr) = const_expr { let mut tmp = *cexpr.clone(); - for (param, arg) in ty_params.iter().zip(ty_args.iter()) { + for ((param, _), arg) in ty_params.iter().zip(ty_args.iter()) { tmp.substitute(param, arg); } tmp @@ -665,7 +666,7 @@ impl Env { expr: ConstExpr, ) -> Result<(), Error> { let associated_const_name = associated_const_name.to_string(); - trace!("Defining associated const {associated_const_name} as {expr} to type {ty}"); + debug!("Defining associated const {associated_const_name} as {expr} to type {ty}"); let expr_ty = expr.get_type(self)?; let mut associated_constants = self.associated_constants.write().unwrap(); associated_constants @@ -677,9 +678,9 @@ impl Env { } /// Add all the declarations to this environment. - pub(super) fn add_declaration(&mut self, declaration: &Declaration) -> Result<(), Error> { + pub(super) fn add_declaration(&mut self, declaration: &Declaration, compiling: bool) -> Result<(), Error> { self.add_compile_time_declaration(declaration)?; - self.add_local_variable_declaration(declaration)?; + self.add_local_variable_declaration(declaration, compiling)?; Ok(()) } @@ -771,10 +772,10 @@ impl Env { let name = alias.clone().unwrap_or(name.clone()); // if !self.types.contains_key(&name) { - self.define_const(&name, access.clone()); if let Ok(Type::Type(ty)) = access.get_type(self) { - self.define_type(name, *ty); + self.define_type(&name, *ty); } + self.define_const(&name, access.clone()); } } Declaration::FromImportAll(module) => { @@ -784,10 +785,10 @@ impl Env { for name in fields.keys() { let access = module.clone().field(ConstExpr::Symbol(name.clone())); - self.define_const(name, access.clone()); if let Ok(Type::Type(ty)) = access.get_type(self) { self.define_type(name, *ty); } + self.define_const(name, access.clone()); } } else { error!("Invalid module type: {module_ty}"); @@ -852,11 +853,10 @@ impl Env { for (name, associated_const) in impls { let templated_const = - associated_const.template(supplied_param_symbols.clone()); + associated_const.template(template_params.clone().into_iter().zip(supplied_param_symbols.clone().into_iter()).map(|((_, ty), param)| (param, ty)).collect()); self.add_associated_const(*template.clone(), name, templated_const)?; } } else { - // ty.add_monomorphized_associated_consts(self)?; for (name, associated_const) in impls { self.add_associated_const(ty.clone(), name, associated_const.clone())?; } @@ -866,24 +866,8 @@ impl Env { // })?; } } - Declaration::Var(_, _, Some(_ty), _e) => { - // ty.add_monomorphized_associated_consts(self).ok(); - // if let Ok(ty) = e.get_type(self) { - // ty.add_monomorphized_associated_consts(self).ok(); - // } - } - Declaration::Var(_, _, _, _e) => { - // Variables are not defined at compile-time. - // if let Ok(ty) = e.get_type(self) { - // ty.add_monomorphized_associated_consts(self).ok(); - // } - } - Declaration::VarPat(_, _e) => { - // Variables are not defined at compile-time. - // if let Ok(ty) = e.get_type(self) { - // ty.add_monomorphized_associated_consts(self).ok(); - // } - } + Declaration::Var(_, _, _, _) => {} + Declaration::VarPat(_, _) => {} Declaration::Many(decls) => { for decl in decls.iter() { self.add_compile_time_declaration(decl)?; @@ -909,6 +893,7 @@ impl Env { pub(super) fn add_local_variable_declaration( &mut self, declaration: &Declaration, + compiling: bool ) -> Result<(), Error> { trace!("Adding local declaration {declaration}"); match declaration { @@ -948,7 +933,7 @@ impl Env { None => expr.get_type(self)?, }; // ty.add_monomorphized_associated_consts(self)?; - self.define_var(name, *mutability, ty)?; + self.define_var(name, *mutability, ty, compiling)?; } Declaration::VarPat(pat, expr) => { let ty = expr.get_type(self)?; @@ -957,7 +942,7 @@ impl Env { } Declaration::Many(decls) => { for decl in decls.iter() { - self.add_local_variable_declaration(decl)?; + self.add_local_variable_declaration(decl, compiling)?; } } } @@ -994,19 +979,28 @@ impl Env { /// Define a type with a given name under this environment. pub(super) fn define_type(&mut self, name: impl ToString, ty: Type) { let name = name.to_string(); - + trace!("Defining type {name} as {ty}"); + if ty.is_const_param() { + if let Ok(ty) = ty.clone().simplify_until_const_param(self, false) { + self.define_const(&name, ty); + return; + } + } match &ty { Type::Symbol(sym) if sym == &name => { trace!("Defining type {ty} to itself as {name}"); } _ => { - trace!("Defining type {name} as {ty}"); Arc::make_mut(&mut self.consts).insert(name.clone(), ConstExpr::Type(ty.clone())); - Arc::make_mut(&mut self.types).insert(name, ty.clone()); + Arc::make_mut(&mut self.types).insert(name.clone(), ty.clone()); - if let Ok(simplified) = ty.simplify_until_concrete(self) { + if let Ok(simplified) = ty.simplify_until_concrete(self, false) { if let Ok(size) = simplified.get_size(self) { - self.set_precalculated_size(simplified, size); + self.set_precalculated_size(simplified.clone(), size); + } + if let Type::ConstParam(cexpr) = simplified { + trace!("Found const param \"{name}\": {cexpr}"); + self.define_const(&name, *cexpr); } } } @@ -1021,34 +1015,8 @@ impl Env { /// typechecking errors if the environment does not already have a memoized size /// for the type of a subexpression. pub fn define_types(&mut self, types: Vec<(String, Type)>) { - for (name, ty) in &types { - match &ty { - Type::Symbol(sym) if sym == name => { - trace!("Defining type {ty} to itself as {name}"); - } - _ => { - if self.types.contains_key(name) { - debug!("Redefining type {name} in {self}"); - } else { - trace!("Defining type {name} as {ty}"); - Arc::make_mut(&mut self.consts) - .insert(name.clone(), ConstExpr::Type(ty.clone())); - Arc::make_mut(&mut self.types).insert(name.clone(), ty.clone()); - } - } - } - } - - for (_, ty) in types { - if let Ok(simplified) = ty.simplify_until_concrete(self) { - if let Ok(size) = simplified.get_size(self) { - self.set_precalculated_size(simplified, size); - } else { - debug!("Failed to memoize type size for {simplified}"); - } - } else { - debug!("Failed to simplify type {ty}"); - } + for (name, ty) in types { + self.define_type(name, ty) } } @@ -1060,6 +1028,7 @@ impl Env { /// Define a constant with a given name under this environment. pub(super) fn define_const(&mut self, name: impl ToString, e: ConstExpr) { let name = name.to_string(); + trace!("Defining constant {name} as {e}"); /* Removed this code in favor of using Declaration::FromImport @@ -1169,6 +1138,7 @@ impl Env { pub(super) fn define_args( &mut self, args: Vec<(String, Mutability, Type)>, + compiling: bool, ) -> Result { debug!("Defining arguments {args:?} in\n{self}"); self.fp_offset = 1; @@ -1177,7 +1147,12 @@ impl Env { // For each argument in reverse order (starting from the last argument) for (name, mutability, ty) in args.into_iter().rev() { // Get the size of the argument we're defining. - let size = ty.get_size(self)?; + let size = if compiling { + ty.get_size(self)? + } else { + 0 + }; + // Add the size of the argument to the total number of cells taken up by the arguments. self.args_size += size; // Decrement the frame pointer offset by the size of the argument @@ -1206,16 +1181,28 @@ impl Env { var: impl ToString, mutability: Mutability, ty: Type, + compiling: bool ) -> Result { let var = var.to_string(); // Get the size of the variable we're defining. - let size = ty.get_size(self)? as isize; + let size = if compiling { + ty.get_size(self)? + } else { + 0 + } as isize; // Remember the offset of the variable under the current scope. let offset = self.fp_offset; // Increment the frame pointer offset by the size of the variable // so that the next variable is allocated directly after this variable. debug!("Defining variable {var} of type {ty} at {offset} in\n{self}"); self.fp_offset += size; + + let ty = match ty { + Type::Type(ty) => *ty, + Type::ConstParam(ty) => ty.get_type(self)?, + other => other + }; + // Store the variable's type and offset in the environment. Arc::make_mut(&mut self.vars).insert(var, (mutability, ty, offset)); // Return the offset of the variable from the frame pointer. @@ -1275,8 +1262,9 @@ impl Env { impl Display for Env { fn fmt(&self, f: &mut Formatter) -> FmtResult { - // return Ok(()); writeln!(f, "Env")?; + // return Ok(()); + /* writeln!(f, " Types:")?; for (name, ty) in self.types.iter() { writeln!(f, " {}: {}", name, ty)?; @@ -1284,19 +1272,19 @@ impl Display for Env { if constants.is_empty() { continue; } - // writeln!(f, " Associated constants:")?; - // for (name, cexpr) in constants { - // writeln!(f, " {}: {}", name, cexpr)?; - // } + writeln!(f, " Associated constants:")?; + for (name, cexpr) in constants { + writeln!(f, " {}: {}", name, cexpr)?; + } + } + writeln!(f, " Constants:")?; + for (i, (name, e)) in self.consts.iter().enumerate() { + writeln!(f, " {i}. {}: {}", name, e)?; + } + writeln!(f, " Procedures:")?; + for (name, proc) in self.procs.iter() { + writeln!(f, " {}: {}", name, proc)?; } - // writeln!(f, " Constants:")?; - // for (i, (name, e)) in self.consts.iter().enumerate() { - // writeln!(f, " {i}. {}: {}", name, e)?; - // } - // writeln!(f, " Procedures:")?; - // for (name, proc) in self.procs.iter() { - // writeln!(f, " {}: {}", name, proc)?; - // } writeln!(f, " Globals:")?; for (name, (mutability, ty, location)) in self.static_vars.iter() { writeln!(f, " {mutability} {name}: {ty} (location {location})")?; @@ -1305,6 +1293,7 @@ impl Display for Env { for (name, (mutability, ty, offset)) in self.vars.iter() { writeln!(f, " {mutability} {name}: {ty} (frame-offset {offset})")?; } + */ Ok(()) } } diff --git a/src/lir/error.rs b/src/lir/error.rs index a85adff8..37b028de 100644 --- a/src/lir/error.rs +++ b/src/lir/error.rs @@ -17,7 +17,11 @@ pub enum Error { ), UnimplementedOperator(String), - + /// An error caused by unexpectedly passing a constant parameter to a template. + UnexpectedConstParam { + found: Type, + expr: Expr + }, /// An error caused by trying to assemble invalid code generated by the compiler. /// This should be taken seriously, unless the error is due to an invalid handwritten builtin. AssemblyError(crate::asm::Error), @@ -158,6 +162,9 @@ impl From for Error { impl Display for Error { fn fmt(&self, f: &mut Formatter) -> FmtResult { match self { + Self::UnexpectedConstParam { found, expr } => { + write!(f, "unexpected constant parameter {found} in expression {expr}") + } Self::Annotated(err, _) => { write!(f, "{err}") } diff --git a/src/lir/expr/const_expr.rs b/src/lir/expr/const_expr.rs index a6a153be..6b68fc2c 100644 --- a/src/lir/expr/const_expr.rs +++ b/src/lir/expr/const_expr.rs @@ -29,6 +29,8 @@ pub enum ConstExpr { /// Bind a list of types in a constant expression. Declare(Box, Box), + /// The expression equal to any other expression. + Any, /// The unit, or "void" instance. None, /// The null pointer constant. @@ -86,7 +88,7 @@ pub enum ConstExpr { /// Monomorphize a constant expression with some type arguments. Monomorphize(Box, Vec), - Template(Vec, Box), + Template(Vec<(String, Option)>, Box), /// Get an attribute of a constant expression. Member(Box, Box), @@ -103,7 +105,23 @@ impl ConstExpr { Self::Monomorphize(Box::new(self), ty_args) } - pub fn template(&self, params: Vec) -> Self { + pub fn equals(&self, other: &Self, env: &Env) -> bool { + debug!("{self} == {other} in const?"); + match (self, other) { + (Self::Any, _) | (_, Self::Any) => true, + (Self::Type(Type::Any), _) | (_, Self::Type(Type::Any)) => true, + (Self::Symbol(name), other) | (other, Self::Symbol(name)) => { + if let Some(c) = env.get_const(name) { + c.equals(other, env) + } else { + &Self::Symbol(name.clone()) == other + } + } + (a, b) => a == b, + } + } + + pub fn template(&self, params: Vec<(String, Option)>) -> Self { match self { Self::Proc(proc) => Self::PolyProc(PolyProcedure::from_mono(proc.clone(), params)), Self::Declare(decls, inner) => inner.template(params).with(decls.clone()), @@ -229,7 +247,7 @@ impl ConstExpr { Self::Member(container, member) => { let container_ty = container.get_type_checked(env, i)?; - trace!("Member access on type: {container_ty}: {container} . {member}"); + debug!("Member access on type: {container_ty:?}: {container} . {member}"); Ok(match (*container.clone(), *member.clone()) { (Self::Annotated(inner, metadata), member) => { Self::Member(inner, member.into()) @@ -296,7 +314,23 @@ impl ConstExpr { trace!("Found struct field: {container_ty} . {member}"); fields[&name].clone().eval_checked(env, i)? } + (Self::Type(ty), Self::Int(n)) => { + warn!("Getting member {n} from {ty}"); + if ty.is_const_param() { + let cexpr = ty.simplify_until_const_param(env, false)?; + return cexpr.field(Self::Int(n)).eval_checked(env, i) + } else { + // return Err(Error::MemberNotFound((*container).into(), *member)); + return Ok(Self::Type(ty).field(Self::Int(n))); + } + } (Self::Type(ty), Self::Symbol(name)) => { + debug!("Getting member {name} from {ty}"); + if ty.is_const_param() { + let cexpr = ty.simplify_until_const_param(env, false)?; + return cexpr.eval_checked(env, i)?.field(Self::Symbol(name)).eval_checked(env, i) + } + if let Some((constant, _)) = env.get_associated_const(&ty, &name) { constant.eval_checked(env, i)? } else { @@ -310,7 +344,7 @@ impl ConstExpr { error!( "Type member access not implemented for: {container_ty} . {member}, symbol {name} not defined" ); - return Err(Error::SymbolNotDefined(name)); + return Ok(Self::Type(ty).field(Self::Symbol(name))); } } @@ -340,7 +374,9 @@ impl ConstExpr { } }) } - Self::None + + Self::Any + | Self::None | Self::Null | Self::Cell(_) | Self::Int(_) @@ -352,8 +388,15 @@ impl ConstExpr { | Self::StandardBuiltin(_) | Self::FFIProcedure(_) | Self::Proc(_) - | Self::PolyProc(_) - | Self::Type(_) => Ok(self), + | Self::PolyProc(_) => Ok(self), + Self::Type(ty) => { + if ty.is_const_param() { + let cexpr = ty.simplify_until_const_param(env, false)?; + cexpr.eval_checked(env, i) + } else { + Ok(Self::Type(ty.clone())) + } + } Self::Declare(bindings, expr) => { debug!("Declaring compile time bindings: {bindings}"); @@ -362,34 +405,42 @@ impl ConstExpr { Ok(expr.eval_checked(&new_env, i)?.with(bindings)) } - Self::Monomorphize(expr, ty_args) => Ok(match expr.clone().eval(env)? { - Self::Template(params, ret) => { - if params.len() != ty_args.len() { - return Err(Error::InvalidMonomorphize(*expr)); + Self::Monomorphize(expr, ty_args) => { + // let ty_args = ty_args.into_iter().map(|t| t.simplify(env)).collect::, _>>()?; + debug!("Monomorphizing {expr} with ty_args {ty_args:?}"); + + Ok(match expr.clone().eval(env)? { + Self::Template(params, ret) => { + if params.len() != ty_args.len() { + return Err(Error::InvalidMonomorphize(*expr)); + } + let mut ret = ret.clone(); + + for ((param, _), ty_arg) in params.iter().zip(ty_args.iter()) { + ret.substitute(param, ty_arg); + } + *ret } - let mut ret = ret.clone(); + Self::PolyProc(proc) => { + Self::Proc(proc.monomorphize(ty_args.clone(), env)?) + }, + Self::Declare(bindings, expr) => { + let mut new_env = env.clone(); + new_env.add_compile_time_declaration(&bindings)?; + expr.monomorphize(ty_args.clone()) + .eval_checked(&new_env, i)? + .with(bindings) + } + Self::Annotated(_inner, metadata) => expr + .monomorphize(ty_args.clone()) + .eval_checked(env, i) + .map_err(|x| x.annotate(metadata))?, - for (param, ty_arg) in params.iter().zip(ty_args.iter()) { - ret.substitute(param, ty_arg); + _other => { + Self::Monomorphize(Box::new(expr.eval_checked(env, i)?), ty_args.clone()) } - *ret - } - Self::PolyProc(proc) => Self::Proc(proc.monomorphize(ty_args.clone(), env)?), - Self::Declare(bindings, expr) => { - let mut new_env = env.clone(); - new_env.add_compile_time_declaration(&bindings)?; - expr.monomorphize(ty_args.clone()) - .eval_checked(&new_env, i)? - .with(bindings) - } - Self::Annotated(_inner, metadata) => expr - .monomorphize(ty_args.clone()) - .eval_checked(env, i) - .map_err(|x| x.annotate(metadata))?, - _other => { - Self::Monomorphize(Box::new(expr.eval_checked(env, i)?), ty_args.clone()) - } - }), + }) + }, Self::TypeOf(expr) => Ok(Self::Array( expr.get_type_checked(env, i)? @@ -514,7 +565,10 @@ impl ConstExpr { // If not, evaluate it and see if it's a symbol. other => match other.eval(env)? { Self::Symbol(name) => Ok(name), - other => Err(Error::NonSymbol(other)), + other => { + // error!("Could not convert {other} to symbol"); + Err(Error::NonSymbol(other)) + }, }, } } @@ -530,15 +584,28 @@ impl GetType for ConstExpr { fn get_type_checked(&self, env: &Env, i: usize) -> Result { trace!("Getting type from constexpr: {self}"); Ok(match self.clone() { + Self::Any => Type::Any, Self::Template(params, expr) => { let mut new_env = env.clone(); - for param in ¶ms { - new_env.define_type(param, Type::Symbol(param.clone())); + for (param, ty) in ¶ms { + if let Some(ty) = ty { + new_env.define_type(param, ty.clone()); + } else { + new_env.define_type(param, Type::Symbol(param.clone())); + } } Type::Poly(params, expr.get_type_checked(&new_env, i)?.into()) } - Self::Type(t) => Type::Type(t.into()), + Self::Type(t) => { + debug!("Getting type of type {t}"); + if t.is_const_param() { + let cexpr = t.simplify_until_const_param(env, false)?; + cexpr.get_type(env)? + } else { + Type::Type(t.into()) + } + } Self::Member(val, field) => { // Get the field to access (as a symbol) @@ -548,10 +615,11 @@ impl GetType for ConstExpr { let as_int = field.clone().as_int(env); let val_type = val.get_type_checked(env, i)?; - debug!("Got type of container access {val} . {field}\nContainer: {val_type}"); - // val_type.add_monomorphized_associated_consts(env)?; + debug!("Got type of container access {val} . {field}\nContainer: {val_type:?}, is_const_param: {}", val_type.is_const_param()); + // Get the type of the value to get the member of. - match &val_type.simplify_until_concrete(env)? { + let val_type = val_type.simplify_until_concrete(env, false)?; + match &val_type { Type::Unit(_unit_name, inner_ty) => { // Get the type of the field. env.get_type_of_associated_const(inner_ty, &as_symbol?) @@ -560,7 +628,7 @@ impl GetType for ConstExpr { Type::Pointer(_found_mutability, t) => { let val = &Expr::ConstExpr(*val); - let t = t.clone().simplify_until_concrete(env)?; + let t = t.clone().simplify_until_concrete(env, false)?; match t.get_member_offset(&field, val, env) { Ok((t, _)) => t, Err(_) => { @@ -575,9 +643,17 @@ impl GetType for ConstExpr { } Type::Type(ty) => { - // Get the associated constant expression's type. - env.get_type_of_associated_const(ty, &as_symbol?) - .ok_or(Error::MemberNotFound((*val.clone()).into(), *field.clone()))? + debug!("Got type {ty}"); + if ty.is_const_param() { + ty.simplify_until_const_param(env, false)?.eval(env)?.field(*field).get_type_checked(env, i)? + } else { + // Get the associated constant expression's type. + if let Ok((ty, _)) = ty.get_member_offset(&field, &Expr::from(self.clone()), env) { + return Ok(ty); + } + env.get_type_of_associated_const(ty, &as_symbol?) + .ok_or(Error::MemberNotFound((*val.clone()).into(), *field.clone()))? + } } // If we're accessing a member of a tuple, // we use the `as_int` interpretation of the field. @@ -640,7 +716,6 @@ impl GetType for ConstExpr { t.clone() } else { // If the field is not in the union, return an error. - // return Err(Error::MemberNotFound((*val.clone()).into(), (*field.clone()).into())); return ConstExpr::Member( ConstExpr::Type(val_type).into(), field.clone(), @@ -707,20 +782,38 @@ impl GetType for ConstExpr { .simplify_until_type_checks(env); } Self::Template(params, ret) => { + debug!("Getting type of monomorphized template {self}"); if params.len() != ty_args.len() { return Err(Error::InvalidMonomorphize(expr)); } let mut ret = ret.clone(); - - for (param, ty_arg) in params.iter().zip(ty_args.iter()) { - ret.substitute(param, ty_arg); + let mut new_env = env.clone(); + for ((param, ty), ty_arg) in params.iter().zip(ty_args.iter()) { + if ty_arg.is_const_param() { + let cexpr = ty_arg.simplify_until_const_param(env, false)?; + if let Some(expected_ty) = ty { + let expected = expected_ty.clone(); + let found = cexpr.get_type_checked(env, i)?; + if !found.equals(expected_ty, env)? { + error!("Mismatch in expected type for constant parameter"); + return Err(Error::MismatchedTypes { expected, found, expr: (cexpr.clone()).into() }) + } + } + ret.substitute(param, ty_arg); + new_env.define_const(param, cexpr.clone()); + } else { + ret.substitute(param, ty_arg); + new_env.define_type(param, ty_arg.clone()); + } } - ret.get_type_checked(env, i)? - .simplify_until_type_checks(env)? + debug!("Result: {ret}"); + let ret = ret.get_type_checked(&new_env, i)? + .simplify_until_poly(&new_env, false)?; + ret } _ => { - // warn!("Monomorphizing non-template: {expr}"); + debug!("Monomorphizing non-template: {expr}"); Type::Apply(Box::new(template_ty.clone()), ty_args.clone()) } }; @@ -810,49 +903,49 @@ impl GetType for ConstExpr { }) } - fn substitute(&mut self, name: &str, subsitution: &Type) { + fn substitute(&mut self, name: &str, substitution: &Type) { match self { Self::Type(t) => { - *t = t.substitute(name, subsitution); + *t = t.substitute(name, substitution); } Self::Template(params, ret) => { - if params.contains(&name.to_string()) { + if params.iter().map(|x| x.0.clone()).collect::>().contains(&name.to_string()) { return; } - ret.substitute(name, subsitution); + ret.substitute(name, substitution); } Self::Member(container, member) => { - container.substitute(name, subsitution); - member.substitute(name, subsitution); + container.substitute(name, substitution); + member.substitute(name, substitution); } Self::Annotated(expr, _) => { - expr.substitute(name, subsitution); + expr.substitute(name, substitution); } Self::As(expr, cast_ty) => { - expr.substitute(name, subsitution); - *cast_ty = cast_ty.substitute(name, subsitution); + expr.substitute(name, substitution); + *cast_ty = cast_ty.substitute(name, substitution); } Self::Declare(bindings, expr) => { - bindings.substitute(name, subsitution); - expr.substitute(name, subsitution); + bindings.substitute(name, substitution); + expr.substitute(name, substitution); } Self::Monomorphize(expr, ty_args) => { - expr.substitute(name, subsitution); + expr.substitute(name, substitution); for ty_arg in ty_args { - *ty_arg = ty_arg.substitute(name, subsitution); + *ty_arg = ty_arg.substitute(name, substitution); } } Self::TypeOf(expr) => { - expr.substitute(name, subsitution); + expr.substitute(name, substitution); } Self::Null => {} Self::None => {} Self::SizeOfType(inner_ty) => { - *inner_ty = inner_ty.substitute(name, subsitution); + *inner_ty = inner_ty.substitute(name, substitution); } Self::SizeOfExpr(expr) => { - expr.substitute(name, subsitution); + expr.substitute(name, substitution); } Self::Cell(_) => {} Self::Int(_) => {} @@ -860,49 +953,51 @@ impl GetType for ConstExpr { Self::Char(_) => {} Self::Bool(_) => {} Self::Of(enum_type, _) => { - *enum_type = enum_type.substitute(name, subsitution); + *enum_type = enum_type.substitute(name, substitution); } Self::Tuple(items) => { for item in items { - item.substitute(name, subsitution); + item.substitute(name, substitution); } } Self::Array(items) => { for item in items { - item.substitute(name, subsitution); + item.substitute(name, substitution); } } Self::Struct(fields) => { for item in fields.values_mut() { - item.substitute(name, subsitution); + item.substitute(name, substitution); } } Self::Union(inner, _, expr) => { - *inner = inner.substitute(name, subsitution); - expr.substitute(name, subsitution); + *inner = inner.substitute(name, substitution); + expr.substitute(name, substitution); } Self::EnumUnion(inner, _, expr) => { - *inner = inner.substitute(name, subsitution); - expr.substitute(name, subsitution); + *inner = inner.substitute(name, substitution); + expr.substitute(name, substitution); } Self::PolyProc(proc) => { - proc.substitute(name, subsitution); + proc.substitute(name, substitution); } Self::Proc(proc) => { - proc.substitute(name, subsitution); + proc.substitute(name, substitution); } Self::CoreBuiltin(builtin) => { - builtin.substitute(name, subsitution); + builtin.substitute(name, substitution); } Self::StandardBuiltin(builtin) => { - builtin.substitute(name, subsitution); + builtin.substitute(name, substitution); } Self::FFIProcedure(ffi_proc) => { - ffi_proc.substitute(name, subsitution); + ffi_proc.substitute(name, substitution); } - Self::Symbol(_) => { + Self::Symbol(symbol_name) if symbol_name == name => { // A constant symbol cannot be substituted for a type variable. + *self = ConstExpr::Type(substitution.clone()); } + _ => {} } } } @@ -910,10 +1005,14 @@ impl GetType for ConstExpr { impl fmt::Display for ConstExpr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { + Self::Any => write!(f, "any"), Self::Template(params, expr) => { write!(f, "<")?; - for (i, param) in params.iter().enumerate() { + for (i, (param, ty)) in params.iter().enumerate() { write!(f, "{param}")?; + if let Some(ty) = ty { + write!(f, ": {ty}")?; + } if i < params.len() - 1 { write!(f, ", ")? } @@ -1034,9 +1133,10 @@ impl Hash for ConstExpr { container.hash(state); member.hash(state); } - Self::Annotated(expr, _) => { + Self::Annotated(expr, _metadata) => { state.write_u8(3); expr.hash(state); + // metadata.hash(state); } Self::FFIProcedure(ffi_proc) => { state.write_u8(4); @@ -1144,8 +1244,27 @@ impl Hash for ConstExpr { state.write_u8(28); ty.hash(state); } + Self::Any => state.write_u8(29), } } } impl Eq for ConstExpr {} + +impl From for ConstExpr { + fn from(value: PolyProcedure) -> Self { + Self::PolyProc(value) + } +} + +impl From for ConstExpr { + fn from(value: Procedure) -> Self { + Self::Proc(value) + } +} + +impl From for ConstExpr { + fn from(value: Type) -> Self { + Self::Type(value) + } +} \ No newline at end of file diff --git a/src/lir/expr/declaration.rs b/src/lir/expr/declaration.rs index 3ae12d37..7753c0dc 100644 --- a/src/lir/expr/declaration.rs +++ b/src/lir/expr/declaration.rs @@ -235,7 +235,7 @@ impl Declaration { expr.clone().compile_expr(env, output)?; // Add the variable to the environment, so that it can be used in the body. - env.add_local_variable_declaration(self)?; + env.add_local_variable_declaration(self, true)?; // Log the instructions for the declaration. output.log_instructions_after(name, &log_message, current_instruction); } @@ -511,9 +511,6 @@ impl TypeCheck for Declaration { let bindings = pat.get_bindings(expr, &ty, env)?; // Get the size of all the bindings let size_of_bindings = bindings - // .iter() - // .map(|(_name, (_mut, ty))| ty.get_size(env).unwrap_or(0)) - // .sum::(); .values() .collect::>() .par_iter() @@ -571,7 +568,7 @@ impl TypeCheck for Declaration { for (name, associated_const) in impls { let templated_const = - associated_const.template(supplied_param_symbols.clone()); + associated_const.template(template_params.clone().into_iter().zip(supplied_param_symbols.clone().into_iter()).map(|((_, ty), param)| (param, ty)).collect()); new_env.add_associated_const( *template.clone(), name, @@ -584,10 +581,6 @@ impl TypeCheck for Declaration { // If we are at the limit of parallel recursion, then we should // type check the associated constants sequentially. - // for templated_const in templated_consts { - // templated_const.type_check(&new_env)?; - // } - templated_consts .par_iter() .try_for_each(|templated_const| templated_const.type_check(&new_env))?; @@ -606,7 +599,7 @@ impl TypeCheck for Declaration { Self::Many(decls) => { let mut new_env = env.clone(); // Add all the compile-time declarations to the environment. - new_env.add_declaration(&self.clone())?; + new_env.add_declaration(&self.clone(), false)?; // Get all the compile time declarations so we can type check them in parallel. let (comp_time_decls, run_time_decls): (Vec<_>, Vec<_>) = decls @@ -626,7 +619,7 @@ impl TypeCheck for Declaration { // .map(|decl| decl.type_check(&new_env)) .try_for_each(|decl| { decl.type_check(&new_env)?; - new_env.add_declaration(decl) + new_env.add_declaration(decl, false) })?; /* @@ -672,15 +665,13 @@ impl TypeCheck for Declaration { let mut new_env = env.clone(); // Add all the compile-time declarations to the environment. - // new_env.add_compile_time_declaration(&Self::Many(decls.clone()))?; - new_env.add_declaration(&Self::Many(decls.clone()))?; + new_env.add_declaration(&Self::Many(decls.clone()), false)?; trace!("Typechecking module {}", name); // Get all the compile time declarations so we can type check them in parallel. let (comp_time_decls, _run_time_decls): (Vec<_>, Vec<_>) = decls .iter() .partition(|decl| decl.is_compile_time_declaration()); - // trace!("Compile time declarations: {:?}", comp_time_decls); if !comp_time_decls.is_empty() { // Type check all the compile time declarations in parallel. comp_time_decls diff --git a/src/lir/expr/expression.rs b/src/lir/expr/expression.rs index c0335428..7c5f1010 100644 --- a/src/lir/expr/expression.rs +++ b/src/lir/expr/expression.rs @@ -236,7 +236,6 @@ impl Expr { // Check if the value actually has a member with this name. let val_type = val.get_type(env)?; - // val_type.add_monomorphized_associated_consts(env)?; trace!(target: "member", "got value type: {:#?}: {val}.{name}", val_type); // If the value has a member with this name, trace!(target: "member", "WHOOP WHOOP"); @@ -246,21 +245,12 @@ impl Expr { error!(target: "member", "Symbol not defined: {name} while getting member"); Error::SymbolNotDefined(name.clone()) })?; - // .monomorphize(ty_args.clone()); associated_function = associated_function.monomorphize(ty_args.clone()); associated_function_type = associated_function_type.apply(ty_args.clone()); - // let associated_function = ConstExpr::Type(val_type.clone()) - // .field(*member) - // .monomorphize(ty_args.clone()); + trace!(target: "member", "function value: {associated_function} in {env}"); - // Get the type of the function - // let associated_function_type = env - // .get_type_of_associated_const(&val_type, &name) - // .ok_or_else(|| Error::SymbolNotDefined(name))? - // .apply(ty_args); - // trace!(target: "member", "got function type: {}", associated_function_type); let mut new_args = vec![]; if let Some(expected_mutability) = @@ -313,7 +303,6 @@ impl Expr { let name = name?; // Check if the value actually has a member with this name. let val_type = val.get_type(env)?; - // val_type.add_monomorphized_associated_consts(env)?; trace!(target: "member", "got value type: {:#?}: {val}.{name}", val_type); // If the value has a member with this name, trace!(target: "member", "WHOOP WHOOP"); @@ -325,18 +314,9 @@ impl Expr { Error::SymbolNotDefined(name.clone()) })?; - // let associated_function = env - // .get_associated_const(&val_type, &name) - // .ok_or_else(|| Error::SymbolNotDefined(name.clone()))?; - // let associated_function = ConstExpr::Type(val_type.clone()) - // .field(*member) - // .monomorphize(ty_args.clone()); trace!(target: "member", "function value: {associated_function} in {env}"); // Get the type of the function - // let associated_function_type = env - // .get_type_of_associated_const(&val_type, &name) - // .ok_or_else(|| Error::SymbolNotDefined(name))?; trace!(target: "member", "got function type: {}", associated_function_type); // Get the first argument's type let mut new_args = vec![]; @@ -385,7 +365,6 @@ impl Expr { let name = name?; // Check if the value actually has a member with this name. let val_type = val.get_type(env)?; - // val_type.add_monomorphized_associated_consts(env)?; trace!(target: "member", "got value type: {:#?}: {val}.{name}", val_type); // If the value has a member with this name, trace!(target: "member", "WHOOP WHOOP"); @@ -398,10 +377,6 @@ impl Expr { trace!(target: "member", "function value: {associated_function} in {env}"); // Get the type of the function - // let associated_function_type = env - // .get_type_of_associated_const(&val_type, &name) - // .ok_or_else(|| Error::SymbolNotDefined(name))? - // .clone(); trace!(target: "member", "got function type: {}", associated_function_type); // Get the first argument's type let mut new_args = vec![]; diff --git a/src/lir/expr/ops/arithmetic/mod.rs b/src/lir/expr/ops/arithmetic/mod.rs index 80761512..08424393 100644 --- a/src/lir/expr/ops/arithmetic/mod.rs +++ b/src/lir/expr/ops/arithmetic/mod.rs @@ -32,6 +32,147 @@ pub enum Arithmetic { } impl BinaryOp for Arithmetic { + /// Compiles the operation on the given expressions. + fn compile( + &self, + lhs: &Expr, + rhs: &Expr, + env: &mut Env, + output: &mut dyn AssemblyProgram, + ) -> Result<(), Error> { + if let Expr::Annotated(lhs, metadata) = lhs { + return self + .compile(lhs, rhs, env, output) + .map_err(|err| err.annotate(metadata.clone())); + } + if let Expr::Annotated(rhs, metadata) = rhs { + return self + .compile(lhs, rhs, env, output) + .map_err(|err| err.annotate(metadata.clone())); + } + + // trace!("Compiling binary op: {lhs} {self} {rhs} ({self:?})"); + lhs.clone().compile_expr(env, output)?; + rhs.clone().compile_expr(env, output)?; + // self.compile_types(&, &rhs.get_type(env)?, env, output)?; + let lhs_expr = lhs; + let rhs_expr = rhs; + let lhs = &lhs_expr.get_type(env)?; + let rhs = &rhs_expr.get_type(env)?; + + if let (Type::Array(_, _), Arithmetic::Multiply, Type::Int) = (lhs, self, rhs) { + if !rhs.equals(&Type::Int, env)? { + return Err(Error::MismatchedTypes { expected: Type::Int, found: rhs.clone(), expr: rhs_expr.clone() }) + } + + // Copy the loop RHS times. + // This will just evaluate the array, evaluate the int, and then repeatedly + // copy the array back onto the stack `rhs` times. + let arr_size = lhs.get_size(env)?; + // Copy the integer into a register. + output.op(CoreOp::Many(vec![ + // Pop into B + CoreOp::Pop(Some(B), 1), + // Store the address of the array in A. + CoreOp::GetAddress { + addr: SP.deref().offset(1 - arr_size as isize), + dst: A, + }, + // While B != 0 + CoreOp::Dec(B), + CoreOp::While(B), + // Push the array back onto the stack, starting at A + CoreOp::Push(A.deref(), arr_size), + // Decrement B + CoreOp::Dec(B), + CoreOp::End, + ])); + + return Ok(()); + } + + let src = SP.deref(); + let dst = SP.deref().offset(-1); + let tmp = SP.deref().offset(1); + // Get the respective core operation for the current expression. + let core_op = match self { + Self::Add => CoreOp::Add { src, dst }, + Self::Subtract => CoreOp::Sub { src, dst }, + Self::Multiply => CoreOp::Mul { src, dst }, + Self::Divide => CoreOp::Div { src, dst }, + Self::Remainder => CoreOp::Rem { src, dst }, + Self::Power => CoreOp::Many(vec![ + // We can't use the `Pow` operation, because it's not supported by + // the core variant. So we have to do it with a loop. + CoreOp::Move { + src: dst.clone(), + dst: tmp.clone(), + }, + CoreOp::Set(dst.clone(), 1), + CoreOp::While(src.clone()), + CoreOp::Mul { src: tmp, dst }, + CoreOp::Dec(src), + CoreOp::End, + ]), + }; + let src = SP.deref(); + let dst = SP.deref().offset(-1); + // Get the respective standard operation for the current expression. + let std_op = match self { + Self::Add => StandardOp::Add { src, dst }, + Self::Subtract => StandardOp::Sub { src, dst }, + Self::Multiply => StandardOp::Mul { src, dst }, + Self::Divide => StandardOp::Div { src, dst }, + Self::Remainder => StandardOp::Rem { src, dst }, + Self::Power => StandardOp::Pow { src, dst }, + }; + // Now, perform the correct assembly expressions based on the types of the two expressions. + match (lhs, rhs) { + // If a `Float` and a `Cell` are used, we just interpret the `Cell` as a `Float`. + (Type::Cell, Type::Float) | (Type::Float, Type::Cell) => { + output.std_op(std_op)?; + } + // Two floats are used as floats. + (Type::Float, Type::Float) => { + output.std_op(std_op)?; + } + // An integer used with a float is promoted, and returns a float. + (Type::Int, Type::Float) => { + output.std_op(StandardOp::ToFloat(SP.deref().offset(-1)))?; + output.std_op(std_op)?; + } + (Type::Float, Type::Int) => { + output.std_op(StandardOp::ToFloat(SP.deref()))?; + output.std_op(std_op)?; + } + + // If cells and/or ints are used, we just use them as integers. + (Type::Int, Type::Int) + | (Type::Cell, Type::Cell) + | (Type::Cell, Type::Int) + | (Type::Int, Type::Cell) => { + output.op(core_op); + } + + (Type::Unit(_name1, a_type), Type::Unit(_name2, b_type)) => { + return self.compile_types(a_type, b_type, env, output); + } + + // Cannot do arithmetic on other pairs of types. + _ => { + return Err(Error::InvalidBinaryOpTypes( + Box::new(*self), + lhs.clone(), + rhs.clone(), + )) + } + } + // Pop `b` off of the stack: we only needed it to evaluate + // the arithmetic and store the result to `a` on the stack. + output.op(CoreOp::Pop(None, 1)); + Ok(()) + } + /// Can this binary operation be applied to the given types? fn can_apply(&self, lhs: &Type, rhs: &Type, env: &Env) -> Result { match (lhs, rhs) { @@ -40,6 +181,7 @@ impl BinaryOp for Arithmetic { Ok(true) } (Type::Array(_, _), Type::Int) => Ok(matches!(self, Self::Multiply)), + (Type::Array(_, _), Type::Type(..)) => Ok(matches!(self, Self::Multiply)), (Type::Int | Type::Float | Type::Cell, Type::Cell) | (Type::Cell, Type::Int | Type::Float) => Ok(true), @@ -75,8 +217,10 @@ impl BinaryOp for Arithmetic { .return_type(lhs, rhs, env) .map_err(|e| e.annotate(metadata.clone())); } + let lhs_ty = lhs.get_type(env)?; + let rhs_ty = rhs.get_type(env)?; - Ok(match (lhs.get_type(env)?, rhs.get_type(env)?) { + let result = Ok(match (lhs_ty.discard_type_wrapper(), rhs_ty.discard_type_wrapper()) { (Type::Int, Type::Int) => Type::Int, (Type::Int, Type::Float) | (Type::Float, Type::Int) | (Type::Float, Type::Float) => { Type::Float @@ -84,19 +228,22 @@ impl BinaryOp for Arithmetic { (Type::Int | Type::Float | Type::Cell, Type::Cell) | (Type::Cell, Type::Int | Type::Float) => Type::Cell, - (Type::Array(elem, size), Type::Int) => { + (Type::Array(elem, size), _other) => { if let (Self::Multiply, Expr::ConstExpr(const_rhs)) = (self, rhs) { let size = size.as_int(env)?; - let n = const_rhs.clone().as_int(env)?; - if n <= 0 { - error!("Cannot multiply array {lhs} by {n} (not positive)"); - return Err(Error::InvalidBinaryOp( - Box::new(*self), - lhs.clone(), - rhs.clone(), - )); + if let Ok(n) = const_rhs.clone().as_int(env) { + if n <= 0 { + error!("Cannot multiply array {lhs} by {n} (not positive)"); + return Err(Error::InvalidBinaryOp( + Box::new(*self), + lhs.clone(), + rhs.clone(), + )); + } + Type::Array(elem, Box::new(ConstExpr::Int(size * n))) + } else { + Type::Array(elem, Box::new(ConstExpr::Any)) } - Type::Array(elem, Box::new(ConstExpr::Int(size * n))) } else { error!("Cannot multiply array {lhs} by {rhs} (not constant = {rhs:?})"); return Err(Error::InvalidBinaryOp( @@ -120,6 +267,7 @@ impl BinaryOp for Arithmetic { (Type::Unit(name1, a_type), Type::Unit(name2, b_type)) => { // Make sure that the two units are the same. if name1 != name2 { + error!("{name1} is not {name2}"); return Err(Error::InvalidBinaryOp( Box::new(*self), lhs.clone(), @@ -129,6 +277,7 @@ impl BinaryOp for Arithmetic { // Make sure that inner types are compatible. if !a_type.equals(&b_type, env)? { + error!("{a_type} is not {b_type}"); return Err(Error::InvalidBinaryOp( Box::new(*self), lhs.clone(), @@ -138,14 +287,16 @@ impl BinaryOp for Arithmetic { Type::Unit(name1, a_type) } - _ => { + (a, b) => { + error!("Unhandled case {a} {self} {b}"); return Err(Error::InvalidBinaryOp( Box::new(*self), lhs.clone(), rhs.clone(), )) } - }) + }); + result } /// Evaluate this binary operation on the given constant values. @@ -252,117 +403,11 @@ impl BinaryOp for Arithmetic { /// Compile the binary operation. fn compile_types( &self, - lhs: &Type, - rhs: &Type, - env: &mut Env, - output: &mut dyn AssemblyProgram, + _lhs: &Type, + _rhs: &Type, + _env: &mut Env, + _output: &mut dyn AssemblyProgram, ) -> Result<(), Error> { - if let (Type::Array(_, _), Arithmetic::Multiply, Type::Int) = (lhs, self, rhs) { - // Copy the loop RHS times. - // This will just evaluate the array, evaluate the int, and then repeatedly - // copy the array back onto the stack `rhs` times. - let arr_size = lhs.get_size(env)?; - // Copy the integer into a register. - output.op(CoreOp::Many(vec![ - // Pop into B - CoreOp::Pop(Some(B), 1), - // Store the address of the array in A. - CoreOp::GetAddress { - addr: SP.deref().offset(1 - arr_size as isize), - dst: A, - }, - // While B != 0 - CoreOp::Dec(B), - CoreOp::While(B), - // Push the array back onto the stack, starting at A - CoreOp::Push(A.deref(), arr_size), - // Decrement B - CoreOp::Dec(B), - CoreOp::End, - ])); - - return Ok(()); - } - - let src = SP.deref(); - let dst = SP.deref().offset(-1); - let tmp = SP.deref().offset(1); - // Get the respective core operation for the current expression. - let core_op = match self { - Self::Add => CoreOp::Add { src, dst }, - Self::Subtract => CoreOp::Sub { src, dst }, - Self::Multiply => CoreOp::Mul { src, dst }, - Self::Divide => CoreOp::Div { src, dst }, - Self::Remainder => CoreOp::Rem { src, dst }, - Self::Power => CoreOp::Many(vec![ - // We can't use the `Pow` operation, because it's not supported by - // the core variant. So we have to do it with a loop. - CoreOp::Move { - src: dst.clone(), - dst: tmp.clone(), - }, - CoreOp::Set(dst.clone(), 1), - CoreOp::While(src.clone()), - CoreOp::Mul { src: tmp, dst }, - CoreOp::Dec(src), - CoreOp::End, - ]), - }; - let src = SP.deref(); - let dst = SP.deref().offset(-1); - // Get the respective standard operation for the current expression. - let std_op = match self { - Self::Add => StandardOp::Add { src, dst }, - Self::Subtract => StandardOp::Sub { src, dst }, - Self::Multiply => StandardOp::Mul { src, dst }, - Self::Divide => StandardOp::Div { src, dst }, - Self::Remainder => StandardOp::Rem { src, dst }, - Self::Power => StandardOp::Pow { src, dst }, - }; - // Now, perform the correct assembly expressions based on the types of the two expressions. - match (lhs, rhs) { - // If a `Float` and a `Cell` are used, we just interpret the `Cell` as a `Float`. - (Type::Cell, Type::Float) | (Type::Float, Type::Cell) => { - output.std_op(std_op)?; - } - // Two floats are used as floats. - (Type::Float, Type::Float) => { - output.std_op(std_op)?; - } - // An integer used with a float is promoted, and returns a float. - (Type::Int, Type::Float) => { - output.std_op(StandardOp::ToFloat(SP.deref().offset(-1)))?; - output.std_op(std_op)?; - } - (Type::Float, Type::Int) => { - output.std_op(StandardOp::ToFloat(SP.deref()))?; - output.std_op(std_op)?; - } - - // If cells and/or ints are used, we just use them as integers. - (Type::Int, Type::Int) - | (Type::Cell, Type::Cell) - | (Type::Cell, Type::Int) - | (Type::Int, Type::Cell) => { - output.op(core_op); - } - - (Type::Unit(_name1, a_type), Type::Unit(_name2, b_type)) => { - return self.compile_types(a_type, b_type, env, output); - } - - // Cannot do arithmetic on other pairs of types. - _ => { - return Err(Error::InvalidBinaryOpTypes( - Box::new(*self), - lhs.clone(), - rhs.clone(), - )) - } - } - // Pop `b` off of the stack: we only needed it to evaluate - // the arithmetic and store the result to `a` on the stack. - output.op(CoreOp::Pop(None, 1)); Ok(()) } diff --git a/src/lir/expr/ops/comparison.rs b/src/lir/expr/ops/comparison.rs index fdf5630a..eff743c2 100644 --- a/src/lir/expr/ops/comparison.rs +++ b/src/lir/expr/ops/comparison.rs @@ -23,7 +23,7 @@ pub enum Comparison { impl BinaryOp for Comparison { /// Can this binary operation be applied to the given types? fn can_apply(&self, lhs: &Type, rhs: &Type, env: &Env) -> Result { - match (lhs, self, rhs) { + match (&lhs.clone().discard_type_wrapper(), self, &rhs.clone().discard_type_wrapper()) { (Type::Int, Self::LessThan, Type::Int) | (Type::Int, Self::LessThanOrEqual, Type::Int) | (Type::Int, Self::GreaterThan, Type::Int) @@ -198,7 +198,7 @@ impl BinaryOp for Comparison { let dst = SP.deref().offset(-1); let tmp = SP.deref().offset(1); // Now, perform the correct assembly expressions based on the types of the two expressions. - match (lhs, self, rhs) { + match (&lhs.clone().discard_type_wrapper(), self, &rhs.clone().discard_type_wrapper()) { // If a `Float` and a `Cell` are used, we just interpret the `Cell` as a `Float`. (Type::Cell, _, Type::Float) | (Type::Float, _, Type::Cell) => { output.op(CoreOp::Move { src: dst, dst: tmp }); diff --git a/src/lir/expr/ops/io.rs b/src/lir/expr/ops/io.rs index c811c76c..c37cd089 100644 --- a/src/lir/expr/ops/io.rs +++ b/src/lir/expr/ops/io.rs @@ -7,13 +7,14 @@ use crate::{ }; use ::core::fmt::{Debug, Display, Formatter, Result as FmtResult}; + #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] pub struct Get; impl UnaryOp for Get { /// Can this unary operation be applied to the given type? fn can_apply(&self, ty: &Type, env: &Env) -> Result { - ty.simplify_until_concrete(env).map(|ty| { + ty.simplify_until_concrete(env, false).map(|ty| { if let Type::Pointer(mutability, x) = ty { match *x { Type::Char | Type::Int | Type::Float => mutability.is_mutable(), @@ -100,7 +101,7 @@ impl Put { env: &mut Env, output: &mut dyn AssemblyProgram, ) -> Result<(), Error> { - let t = &t.simplify_until_concrete(env)?; + let t = &t.simplify_until_concrete(env, false)?; match t { Type::Type(t) => { for c in format!("{}", t).chars() { @@ -430,7 +431,7 @@ impl Put { env: &mut Env, output: &mut dyn AssemblyProgram, ) -> Result<(), Error> { - let t = &t.simplify_until_concrete(env)?; + let t = &t.simplify_until_concrete(env, false)?; match t { Type::Cell => { output.op(CoreOp::Put(addr, Output::stdout_int())); @@ -597,7 +598,7 @@ impl UnaryOp for Put { // Get the size of the type. let size = ty.get_size(env)? as isize; - let ty = &ty.simplify_until_concrete(env)?; + let ty = &ty.simplify_until_concrete(env, false)?; // Calculate the address of the expression on the stack. let addr = SP.deref().offset(-size + 1); diff --git a/src/lir/expr/ops/mod.rs b/src/lir/expr/ops/mod.rs index c3357ea5..fb22fe61 100644 --- a/src/lir/expr/ops/mod.rs +++ b/src/lir/expr/ops/mod.rs @@ -311,6 +311,7 @@ pub trait BinaryOp: std::fmt::Debug + std::fmt::Display + Send + Sync { self.compile_types(&lhs.get_type(env)?, &rhs.get_type(env)?, env, output)?; Ok(()) } + /// Compiles the operation on the given types. (Generates the code for the operation.) fn compile_types( &self, diff --git a/src/lir/expr/ops/tagged_union.rs b/src/lir/expr/ops/tagged_union.rs index ebc80634..ac2e8d1b 100644 --- a/src/lir/expr/ops/tagged_union.rs +++ b/src/lir/expr/ops/tagged_union.rs @@ -12,12 +12,12 @@ impl UnaryOp for Tag { /// Can this unary operation be applied to the given type? fn can_apply(&self, ty: &Type, env: &Env) -> Result { let ty = ty.clone().simplify(env)?; - Ok(ty.simplify_until_has_variants(env).is_ok()) + Ok(ty.simplify_until_has_variants(env, false).is_ok()) } /// Get the type of the result of applying this unary operation to the given type. fn return_type(&self, expr: &Expr, env: &Env) -> Result { - let ty = expr.get_type(env)?.simplify_until_has_variants(env)?; + let ty = expr.get_type(env)?.simplify_until_has_variants(env, false)?; match ty { Type::EnumUnion(variants) => Ok(Type::Enum(variants.into_keys().collect())), @@ -101,12 +101,12 @@ impl UnaryOp for Data { /// Can this unary operation be applied to the given type? fn can_apply(&self, ty: &Type, env: &Env) -> Result { let ty = ty.clone().simplify(env)?; - Ok(ty.simplify_until_has_variants(env).is_ok()) + Ok(ty.simplify_until_has_variants(env, false).is_ok()) } /// Get the type of the result of applying this unary operation to the given type. fn return_type(&self, expr: &Expr, env: &Env) -> Result { - let ty = expr.get_type(env)?.simplify_until_has_variants(env)?; + let ty = expr.get_type(env)?.simplify_until_has_variants(env, false)?; match ty { Type::EnumUnion(variants) => Ok(Type::Union(variants)), diff --git a/src/lir/expr/pattern.rs b/src/lir/expr/pattern.rs index fbf37e67..5afb23bc 100644 --- a/src/lir/expr/pattern.rs +++ b/src/lir/expr/pattern.rs @@ -70,14 +70,14 @@ impl Pattern { env: &Env, ) -> Result { // Get the type of the expression being matched. - let ty = expr.get_type(env)?.simplify_until_concrete(env)?; + let ty = expr.get_type(env)?.simplify_until_concrete(env, false)?; // Get the bindings for the pattern. let bindings = self.get_bindings(expr, &ty, env)?; // Create a new environment with the bindings. let mut new_env = env.clone(); for (var, (mutabilty, ty)) in bindings { // Define the variables in the new environment. - new_env.define_var(var, mutabilty, ty)?; + new_env.define_var(var, mutabilty, ty, true)?; } // Get the type of the branch. @@ -98,7 +98,7 @@ impl Pattern { matching_expr_ty: &Type, env: &Env, ) -> Result { - let matching_expr_ty = &matching_expr_ty.simplify_until_concrete(env)?; + let matching_expr_ty = &matching_expr_ty.simplify_until_concrete(env, false)?; match matching_expr_ty { Type::Bool => { // If the type is a boolean, the patterns are exhaustive if they match both `true` and `false`. @@ -389,7 +389,7 @@ impl Pattern { pub fn type_check(&self, matching_expr: &Expr, branch: &Expr, env: &Env) -> Result<(), Error> { trace!("Type checking pattern match: {} => {}", self, branch); // Get the type of the expression being matched. - let matching_ty = matching_expr.get_type(env)?.simplify_until_concrete(env)?; + let matching_ty = matching_expr.get_type(env)?.simplify_until_concrete(env, false)?; // Get the type of the branch as a result of the match. let expected = self.get_branch_result_type(matching_expr, branch, env)?; // Type-check the expression generated to match the pattern. @@ -498,9 +498,9 @@ impl Pattern { // Create a new environment with the bindings let mut new_env = env.clone(); // Get the type of the expression being matched - let match_type = expr.get_type(env)?.simplify_until_concrete(env)?; + let match_type = expr.get_type(env)?.simplify_until_concrete(env, false)?; // Define the variable in the new environment. - new_env.define_var(var_name.clone(), Mutability::Immutable, match_type.clone())?; + new_env.define_var(var_name.clone(), Mutability::Immutable, match_type.clone(), true)?; // Generate the expression which evaluates the `match` expression. let match_expr = Pattern::match_pattern_helper(&Expr::var(&var_name), branches, &new_env)?; @@ -570,7 +570,7 @@ impl Pattern { env: &Env, mut origin: usize, ) -> Result, Error> { - let ty = &ty.simplify_until_concrete(env)?; + let ty = &ty.simplify_until_concrete(env, false)?; Ok(match (self, ty) { // If the pattern is a tuple, and the type is a tuple, then // get the bindings for each element of the tuple. @@ -719,7 +719,7 @@ impl Pattern { /// Does this pattern match the given expression? /// This function returns an expression which evaluates to true if the expression matches the pattern. fn matches(&self, expr: &Expr, ty: &Type, env: &Env) -> Result { - let ty = &ty.simplify_until_concrete(env)?; + let ty = &ty.simplify_until_concrete(env, false)?; Ok(match (self, ty) { // If the pattern is a variant, and the type is a EnumUnion, // check if the variant matches the pattern. @@ -879,7 +879,7 @@ impl Pattern { /// then this will not work correctly. This function does not check the arguments.*** pub fn declare_let_bind(&self, expr: &Expr, ty: &Type, env: &mut Env) -> Result<(), Error> { // Get the type of the expression being matched. - let ty = &ty.simplify_until_concrete(env)?; + let ty = &ty.simplify_until_concrete(env, false)?; // Get the variable bindings for the pattern. // This tells us the type and mutability of each variable. let bindings = self.get_bindings_with_offset(expr, ty, env, 0)?; @@ -890,7 +890,7 @@ impl Pattern { bindings.sort_by_key(|(_, (_, _, offset))| *offset); // Define all the bindings in the environment. for (name, (mutability, ty, _)) in &bindings { - env.define_var(name, *mutability, ty.clone())?; + env.define_var(name, *mutability, ty.clone(), true)?; } Ok(()) } @@ -905,7 +905,7 @@ impl Pattern { /// added to the environment, and will be bound to the corresponding value in /// the expression which is being matched. fn bind(&self, expr: &Expr, ty: &Type, ret: &Expr, env: &Env) -> Result { - let ty = &ty.simplify_until_concrete(env)?; + let ty = &ty.simplify_until_concrete(env, false)?; Ok(match (self, ty) { // If the pattern is a variant, and the type is a tagged union, // bind the pattern to the corresponding variant type in the tagged union. diff --git a/src/lir/expr/procedure/mono.rs b/src/lir/expr/procedure/mono.rs index a2055663..11106f91 100644 --- a/src/lir/expr/procedure/mono.rs +++ b/src/lir/expr/procedure/mono.rs @@ -162,7 +162,7 @@ impl TypeCheck for Procedure { // Create a new scope for the procedure's body, and define the arguments for the scope. let mut new_env = env.new_scope(); - new_env.define_args(self.args.clone())?; + new_env.define_args(self.args.clone(), false)?; new_env.set_expected_return_type(self.ret.clone()); // Get the type of the procedure's body, and confirm that it matches the return type. @@ -212,7 +212,7 @@ impl Compile for Procedure { let mut new_env = env.new_scope(); // Declare the arguments and get their size - let args_size = new_env.define_args(self.args)?; + let args_size = new_env.define_args(self.args, true)?; // Get the size of the return value to leave on the stack let ret_size = self.ret.get_size(env)?; diff --git a/src/lir/expr/procedure/poly.rs b/src/lir/expr/procedure/poly.rs index bf5c3c7f..3e87d616 100644 --- a/src/lir/expr/procedure/poly.rs +++ b/src/lir/expr/procedure/poly.rs @@ -12,7 +12,7 @@ use std::{ }; use std::{hash::Hash, hash::Hasher}; -use log::{debug, error, trace}; +use log::{debug, error}; use serde_derive::{Deserialize, Serialize}; /// A polymorphic procedure of LIR code which can be applied to a list of arguments with type arguments. @@ -23,7 +23,7 @@ pub struct PolyProcedure { /// The name of the procedure. name: String, /// The type parameters of the procedure. - ty_params: Vec, + ty_params: Vec<(String, Option)>, /// The arguments of the procedure. args: Vec<(String, Mutability, Type)>, /// The return type of the procedure. @@ -52,7 +52,7 @@ impl PolyProcedure { /// a return type, and the body of the procedure. pub fn new( name: String, - ty_params: Vec, + ty_params: Vec<(String, Option)>, args: Vec<(String, Mutability, Type)>, ret: Type, body: impl Into, @@ -77,7 +77,11 @@ impl PolyProcedure { } } - pub fn from_mono(mono: Procedure, ty_params: Vec) -> Self { + pub fn get_type_params(&self) -> &Vec<(String, Option)> { + &self.ty_params + } + + pub fn from_mono(mono: Procedure, ty_params: Vec<(String, Option)>) -> Self { debug!(target: "mono", "Creating polymorphic procedure from monomorph {}", mono); let name = mono .get_common_name() @@ -102,6 +106,10 @@ impl PolyProcedure { &self.name } + fn type_param_names(&self) -> Vec { + self.ty_params.clone().into_iter().map(|(ty, _)| ty).collect() + } + /// Take some type arguments and produce a monomorphized version of the procedure. /// This monomorphized version can then be compiled directly. Additionally, the /// mono version of the procedure is memoized, so that it is only compiled once. @@ -117,7 +125,7 @@ impl PolyProcedure { .into_iter() .map(|ty| { // Simplify the type until it is concrete - let concrete = ty.simplify_until_concrete(env)?; + let concrete = ty.simplify_until_concrete(env, true)?; // concrete.add_monomorphized_associated_consts(env)?; Ok(concrete) }) @@ -134,7 +142,7 @@ impl PolyProcedure { ); // Simplify the type until it is simple. // This reduces to the concrete version of the type application. - let concrete = ty.simplify_until_concrete(env)?; + let concrete = ty.simplify_until_concrete(env, true)?; // concrete.add_monomorphized_associated_consts(env)?; Ok(concrete) }; @@ -163,30 +171,29 @@ impl PolyProcedure { drop(monomorphs); let mut monomorphs = self.monomorphs.write().unwrap(); + debug!(target: "mono", "Memoizing monomorphized procedure {}", mangled_name); + let mut body = *self.body.clone(); + + // Substitute the type arguments into the body of the function. + body.substitute_types(&self.type_param_names(), &simplified_ty_args); + + // Wrap the body in a let expression to bind the type arguments. + body = body.with( + self.type_param_names() + .iter() + .zip(simplified_ty_args.iter()) + .map(|(a, b)| (a.clone(), b.clone())) + .collect::>(), + ); + + let monomorph = Procedure::new(Some(mangled_name.clone()), args, ret, body); + // If the monomorphized procedure has already been memoized, return it, otherwise memoize it. debug!(target: "mono", "Inserting entry for {}", mangled_name); let monomorph = monomorphs .entry(mangled_name.clone()) - .or_insert_with(|| { - debug!(target: "mono", "Memoizing monomorphized procedure {}", mangled_name); - let mut body = *self.body.clone(); - - // Substitute the type arguments into the body of the function. - body.substitute_types(&self.ty_params, &simplified_ty_args); - - // Wrap the body in a let expression to bind the type arguments. - body = body.with( - self.ty_params - .iter() - .zip(simplified_ty_args.iter()) - .map(|(a, b)| (a.clone(), b.clone())) - .collect::>(), - ); - - Procedure::new(Some(mangled_name.clone()), args, ret, body) - }) + .or_insert_with(|| monomorph) .clone(); - // Unlock the mutex to prevent a deadlock. drop(monomorphs); // Return the monomorphized procedure. @@ -206,13 +213,19 @@ impl GetType for PolyProcedure { } fn substitute(&mut self, name: &str, ty: &Type) { - if self.ty_params.contains(&name.to_string()) { + if self.type_param_names().contains(&name.to_string()) { + debug!("Not substituting {name} in {ty} because of symbol conflict"); return; } + for (_, ty_arg) in &mut self.ty_params { + *ty_arg = ty_arg.as_mut().map(|ty_arg| ty_arg.substitute(name, ty)); + } + self.args .iter_mut() .for_each(|(_, _, t)| *t = t.substitute(name, ty)); self.ret = self.ret.substitute(name, ty); + self.body.substitute(name, ty); } } @@ -223,19 +236,24 @@ impl TypeCheck for PolyProcedure { } *self.has_type_checked.write().unwrap() = true; - trace!("Type checking {self}"); + debug!("Type checking {self}"); // Create a new scope for the procedure's body, and define the arguments for the scope. let mut new_env = env.new_scope(); + // Define the type parameters of the procedure. - new_env.define_types( - self.ty_params - .clone() - .into_iter() - .map(|ty_param| (ty_param.clone(), Type::Unit(ty_param, Box::new(Type::None)))) - .collect(), - ); + for (name, ty) in &self.ty_params { + match ty { + Some(ty) => { + new_env.define_var(name, Mutability::Immutable, ty.clone(), false)?; + new_env.define_type(name, ty.clone()); + } + None => { + new_env.define_type(name, Type::Unit(name.clone(), Box::new(Type::None))); + } + } + } // Define the arguments of the procedure. - new_env.define_args(self.args.clone())?; + new_env.define_args(self.args.clone(), false)?; new_env.set_expected_return_type(self.ret.clone()); // Typecheck the types of the arguments and return value @@ -245,7 +263,9 @@ impl TypeCheck for PolyProcedure { self.ret.type_check(&new_env)?; // Get the type of the procedure's body, and confirm that it matches the return type. + debug!("Getting body type of {}", self.name); let body_type = self.body.get_type(&new_env)?; + debug!("Got body type {body_type} of {}", self.name); if !body_type.can_decay_to(&self.ret, &new_env)? { error!( @@ -260,6 +280,7 @@ impl TypeCheck for PolyProcedure { }) } else { // Typecheck the procedure's body. + debug!("Typechecking body of {} = {}", self.name, self.body); self.body.type_check(&new_env) } } @@ -268,8 +289,11 @@ impl TypeCheck for PolyProcedure { impl fmt::Display for PolyProcedure { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "proc[")?; - for (i, ty_param) in self.ty_params.iter().enumerate() { + for (i, (ty_param, ty)) in self.ty_params.iter().enumerate() { write!(f, "{}", ty_param)?; + if let Some(ty) = ty { + write!(f, ": {}", ty)?; + } if i < self.ty_params.len() - 1 { write!(f, ", ")?; } diff --git a/src/lir/types/check.rs b/src/lir/types/check.rs index e210a1a0..ba7a7bb2 100644 --- a/src/lir/types/check.rs +++ b/src/lir/types/check.rs @@ -40,6 +40,7 @@ impl TypeCheck for Type { | Self::Char | Self::Enum(_) => Ok(()), + Self::ConstParam(cexpr) => cexpr.type_check(env), Self::Type(t) => t.type_check(env), // Units are sound if their inner type is sound. @@ -47,7 +48,7 @@ impl TypeCheck for Type { // Symbols are sound if they are defined in the environment Self::Symbol(name) => { - if env.get_type(name).is_some() { + if env.get_type(name).is_some() || env.get_const(name).is_some() { Ok(()) } else { debug!("Type {name} not defined in environment {env}"); @@ -69,11 +70,16 @@ impl TypeCheck for Type { // Check the inner type and the length constant-expression. t.type_check(env)?; len.clone().type_check(env)?; + // Check that the length is non-negative. - if len.clone().as_int(env)? < 0 { - // If it is negative, return an error. - error!("Negative array length detected in type {self} in environment {env}"); - return Err(Error::NegativeArrayLength(Expr::ConstExpr(*len.clone()))); + debug!("About to convert {len} to int"); + match len.clone().as_int(env) { + Ok(n) if n < 0 => { + // If it is negative, return an error. + error!("Negative array length detected in type {self} in environment {env}"); + return Err(Error::NegativeArrayLength(Expr::ConstExpr(*len.clone()))); + } + _ => {} } // Otherwise, return success. Ok(()) @@ -129,7 +135,7 @@ impl TypeCheck for Type { ty_params .clone() .into_iter() - .map(|p| (p.clone(), Type::Unit(p, Box::new(Type::Any)))) + .map(|p| (p.0.clone(), Type::Unit(p.0, Box::new(Type::Any)))) .collect(), ); // Check the template type. @@ -152,14 +158,14 @@ impl TypeCheck for Type { .try_for_each(|t| t.type_check(env))?; // Try to confirm that the polymorphic type is a template. - match poly.simplify_until_poly(env)? { + match poly.simplify_until_poly(env, true)? { Type::Symbol(name) => { // Get the type definition. let ty = env .get_type(&name) .ok_or(Error::TypeNotDefined(name.clone()))?; // Check that the type is a template. - match ty.simplify_until_poly(env)? { + match ty.simplify_until_poly(env, true)? { Type::Poly(ty_params, _) => { // Check that the number of type arguments matches the number of type parameters. if ty_args.len() != ty_params.len() { @@ -215,7 +221,7 @@ impl TypeCheck for Expr { // Check the declaration. declaration.type_check(&new_env)?; // Add the declarations to the environment. - new_env.add_declaration(declaration)?; + new_env.add_declaration(declaration, false)?; // Check the body with the declarations defined. body.type_check(&new_env) } @@ -312,7 +318,7 @@ impl TypeCheck for Expr { let bindings = pat.get_bindings(expr, &ty, env)?; // Define the bindings in the environment. for (name, (mutability, ty)) in bindings { - new_env.define_var(name, mutability, ty)?; + new_env.define_var(name, mutability, ty, false)?; } // Check the branch under the new environment. pat.type_check(expr, branch, env)?; @@ -485,7 +491,7 @@ impl TypeCheck for Expr { Err(Error::InvalidRefer(self.clone())) } } - Expr::ConstExpr(_cexpr) => Ok(()), + Expr::ConstExpr(cexpr) => cexpr.type_check(env), Expr::Deref(inner) | Expr::Index(inner, _) => { // Confirm that the inner expression can be referenced. match inner.get_type(env)? { @@ -508,7 +514,9 @@ impl TypeCheck for Expr { inner.refer(*expected_mutability).type_check(env)?; } - _ => {} + ty => { + warn!("Unexpected deref of type {ty}"); + } } e.type_check(env) @@ -574,7 +582,7 @@ impl TypeCheck for Expr { let ptr_type = ptr.get_type(env)?; let val_type = val.get_type(env)?; // Check that the pointer is a pointer. - if let Type::Pointer(mutability, ptr_elem_ty) = ptr_type { + if let Type::Pointer(mutability, ptr_elem_ty) = ptr_type.clone().discard_type_wrapper() { // Check that the type of the value is compatible // with the type of data stored at the pointer's // address. @@ -625,7 +633,7 @@ impl TypeCheck for Expr { f.type_check(env)?; // Get the type of the function. - let f_type = f.get_type(env)?.simplify_until_concrete(env)?; + let f_type = f.get_type(env)?.simplify_until_concrete(env, true)?; // Infer the types of the supplied arguments. let mut found_arg_tys = vec![]; for arg in args { @@ -680,7 +688,7 @@ impl TypeCheck for Expr { } // Get the type of the function. - let f_type = f.get_type(env)?.simplify_until_concrete(env)?; + let f_type = f.get_type(env)?.simplify_until_concrete(env, true)?; // Infer the types of the supplied arguments. let mut found_arg_tys = vec![]; for arg in args { @@ -709,6 +717,8 @@ impl TypeCheck for Expr { found, expr: self.clone(), }); + } else { + debug!("Found {found} can decay to {expected} in {self}") } } Ok(()) @@ -732,9 +742,9 @@ impl TypeCheck for Expr { let expected = env .get_expected_return_type() .cloned() - .unwrap_or(Type::None); + .unwrap_or(Type::None).simplify(env)?; if !found.can_decay_to(&expected, env)? { - error!("The found return type does not match expected type"); + error!("The found return type {found} does not match expected type {expected} in {env}"); return Err(Error::MismatchedTypes { expected, found, @@ -783,7 +793,7 @@ impl TypeCheck for Expr { Self::Union(t, field, val) => { // Typecheck the type. t.type_check(env)?; - let t = t.simplify_until_union(env)?; + let t = t.simplify_until_union(env, true)?; match t { Type::Union(fields) => { // Confirm that the variant is a valid variant. @@ -817,7 +827,7 @@ impl TypeCheck for Expr { Self::EnumUnion(t, variant, val) => { // Typecheck the type t.type_check(env)?; - let t = t.simplify_until_union(env)?; + let t = t.simplify_until_union(env, true)?; match t { Type::EnumUnion(fields) => { @@ -876,7 +886,7 @@ impl TypeCheck for Expr { match e_type.type_check_member(field, e, env) { Ok(_) => Ok(()), Err(e) => { - warn!("Type {e_type} doesn't have member {field} in environment {env}"); + debug!("Type {e_type} doesn't have member {field} in environment {env}"); match field .clone() .as_symbol(env) @@ -925,26 +935,26 @@ impl TypeCheck for Expr { // Typecheck a constant expression. impl TypeCheck for ConstExpr { fn type_check(&self, env: &Env) -> Result<(), Error> { + debug!("Typechecking constant expression: {}", self); if env.has_type_checked_const(self) { return Ok(()); } - debug!("Typechecking constant expression: {}", self); match self { - Self::Template(_ty_params, _template) => { + Self::Any => Ok(()), + Self::Template(ty_params, template) => { // Create a new environment with the type parameters defined. - // let mut new_env = env.clone(); - // // Define the type parameters in the environment. - // new_env.define_types( - // ty_params - // .clone() - // .into_iter() - // .map(|p| (p.clone(), Type::Unit(p, Box::new(Type::None)))) - // .collect(), - // ); + let mut new_env = env.clone(); + for (name, ty) in ty_params { + if let Some(ty) = ty { + new_env.define_type(name, ty.clone()); + new_env.define_var(name, Mutability::Immutable, ty.clone(), false)?; + } else { + new_env.define_type(name, Type::Unit(name.clone(), Box::new(Type::None))) + } + } // Check the template type. - // template.type_check(&new_env) - Ok(()) + template.type_check(&new_env) } Self::Annotated(expr, metadata) => expr @@ -960,26 +970,25 @@ impl TypeCheck for ConstExpr { e.type_check(env)?; // Get the type of the expression. let e_type = e.get_type(env)?; - // e_type.add_monomorphized_associated_consts(env)?; // Typecheck the member we want to access. match e_type.type_check_member(field, &Expr::ConstExpr(*e.clone()), env) { Ok(_) => Ok(()), Err(_err) => { - warn!("Member {field} not found in type {e_type} in environment {env}"); + debug!("Member {field} not found in type {e_type} in environment {env}"); match field .clone() .as_symbol(env) .map(|name| env.get_associated_const(&e_type, &name)) { Ok(_) => { - warn!("Associated constant {field} found in type {e_type} in environment {env}"); + debug!("Associated constant {field} found in type {e_type} in environment {env}"); Ok(()) } // Err(_) => Err(e), Err(_) => { // Try to perform the member op as a regular member op. - warn!("Associated constant {field} not found in type {e_type} in environment {env}"); - warn!("Falling back on regular member access"); + debug!("Associated constant {field} not found in type {e_type} in environment {env}"); + debug!("Falling back on regular member access"); Expr::Member(Box::new(Expr::ConstExpr(*e.clone())), *field.clone()) .type_check(env) } @@ -1020,45 +1029,54 @@ impl TypeCheck for ConstExpr { debug!( "Monomorphizing {expr} with type arguments {ty_args:?} in environment {env}" ); - match **expr { + match *expr.clone() { Self::Template(ref ty_params, ref template) => { // Create a new environment with the type parameters defined. - let mut new_env = env.clone(); // Define the type parameters in the environment. - new_env.define_types( - ty_params.clone().into_iter().zip(ty_args.clone()).collect(), - ); + let mut ret = template.clone(); + let mut new_env = env.clone(); + for ((param, ty), ty_arg) in ty_params.iter().zip(ty_args.iter()) { + if ty_arg.is_const_param() { + let cexpr = ty_arg.simplify_until_const_param(env, true)?; + if let Some(expected_ty) = ty { + let expected = expected_ty.clone(); + let found = cexpr.get_type(env)?; + if !found.equals(expected_ty, env)? { + error!("Mismatch in expected type for constant parameter"); + return Err(Error::MismatchedTypes { expected, found, expr: (cexpr.clone()).into() }) + } + } + ret.substitute(param, ty_arg); + new_env.define_const(param, cexpr.clone()); + } else { + ret.substitute(param, ty_arg); + new_env.define_type(param, ty_arg.clone()); + } + } + debug!("Result: {ret}"); + let ret = ret.get_type(&new_env)? + .simplify_until_poly(&new_env, true)?; // Check the template type. - template.type_check(&new_env) - // Ok(()) + ret.type_check(&new_env) } Self::PolyProc(ref poly) => { - // poly.monomorphize(ty_args.clone(), env)?.type_check(env) // Create a new environment with the type parameters defined. - // let mut new_env = env.clone(); - // // Define the type parameters in the environment. - // new_env.define_types( - // poly.ty_params - // .clone() - // .into_iter() - // .zip(ty_args.clone()) - // .collect(), - // ); + let mut new_env = env.clone(); + // Define the type parameters in the environment. + new_env.define_types( + poly.get_type_params() + .clone() + .into_iter() + .map(|(name, _)| name) + .zip(ty_args.clone()) + .collect(), + ); // Check the template type. poly.type_check(env) - // Ok(()) } _ => { self.get_type(env)?.type_check(env)?; expr.type_check(env)?; - // if let Self::PolyProc(poly) = *expr.clone() { - // poly.type_check(env)? - // } - /* - for ty in ty_args { - ty.type_check(env)?; - } - */ ty_args .into_par_iter() .try_for_each(|ty| ty.type_check(env))?; @@ -1121,7 +1139,7 @@ impl TypeCheck for ConstExpr { // Typecheck a variant of an enum. Self::Of(t, variant) => { let t = t - .simplify_until_has_variants(env) + .simplify_until_has_variants(env, true) .map_err(|_| Error::VariantNotFound(t.clone(), variant.clone()))?; match t { @@ -1243,7 +1261,7 @@ impl TypeCheck for ConstExpr { // Typecheck a union literal. Self::Union(t, field, val) => { // Confirm the type supplied is a union. - let t = t.simplify_until_union(env)?; + let t = t.simplify_until_union(env, true)?; match t { Type::Union(fields) => { @@ -1282,7 +1300,7 @@ impl TypeCheck for ConstExpr { // Typecheck a tagged union literal. Self::EnumUnion(t, variant, val) => { // Confirm the type supplied is a union. - let t = t.simplify_until_union(env)?; + let t = t.simplify_until_union(env, true)?; match t { Type::EnumUnion(fields) => { // Confirm that the variant is a valid variant. diff --git a/src/lir/types/inference.rs b/src/lir/types/inference.rs index 73cfa50b..3fd7b831 100644 --- a/src/lir/types/inference.rs +++ b/src/lir/types/inference.rs @@ -57,7 +57,7 @@ impl GetType for Expr { // Create a new environment with the declarations. let mut new_env = env.clone(); // Add the declarations to the environment. - new_env.add_declaration(declaration)?; + new_env.add_declaration(declaration, false)?; // Get the type of the body in the new environment. body.get_type_checked(&new_env, i)? } @@ -232,7 +232,7 @@ impl GetType for Expr { // Get the type of the expression. let t = expr .get_type_checked(env, i)? - .simplify_until_concrete(env)?; + .simplify_until_concrete(env, false)?; // If the type is a pointer, return the inner type of the pointer. if let Type::Pointer(_, inner) = t { // If the type *evaluates* to a pointer, return that inner type. @@ -253,7 +253,7 @@ impl GetType for Expr { // Get the type of the function. let ty = func .get_type_checked(env, i)? - .simplify_until_concrete(env)?; + .simplify_until_concrete(env, false)?; match ty { Type::Proc(_, ret) => *ret, _ => return Err(Error::ApplyNonProc(self.clone())), @@ -313,12 +313,10 @@ impl GetType for Expr { // Get the type of the value to get the member of. let val_type = val.get_type_checked(env, i)?; // val_type.add_monomorphized_associated_consts(env)?; - let val_type = val_type.simplify_until_concrete(env)?; + let val_type = val_type.simplify_until_concrete(env, false)?; // val_type.add_monomorphized_associated_consts(env)?; match val_type { Type::Type(ty) => { - // ty.add_monomorphized_associated_consts(env)?; - // Get the associated constant expression's type. env.get_type_of_associated_const(&ty, &as_symbol?) .ok_or(Error::MemberNotFound(*val.clone(), field.clone()))? diff --git a/src/lir/types/mod.rs b/src/lir/types/mod.rs index 6bf4a206..fa6e03c4 100644 --- a/src/lir/types/mod.rs +++ b/src/lir/types/mod.rs @@ -191,11 +191,15 @@ pub enum Type { /// The type takes a list of symbols that are substituted with concrete types. /// The type is then simplified to a concrete type when combined with `Apply`. /// This type is used to implement generics. - Poly(Vec, Box), + Poly(Vec<(String, Option)>, Box), /// A type that constructs a concrete type from a polymorphic type. /// This type is used to implement generics. Apply(Box, Vec), + + /// A constant literal used in a type expression, like a template application + /// with a constant parameter. + ConstParam(Box), } lazy_static::lazy_static! { @@ -216,6 +220,28 @@ impl Type { self.is_recursive_helper(&mut symbols, env) } + /// Is this type a constant parameter? + /// + /// This will recursively detect if the subtypes are constant parameters as well + pub fn is_const_param(&self) -> bool { + match self { + Type::ConstParam(..) => true, + Type::Struct(fields) => fields.iter().map(|(_name, ty)| ty).all(Self::is_const_param), + Type::Tuple(items) => items.iter().all(Self::is_const_param), + Type::Type(t) => t.is_const_param(), + _ => false, + } + } + + /// Discard the wrappers of Type::Type and Type::Unit + pub(crate) fn discard_type_wrapper(self) -> Self { + match self { + Self::Type(ty) | Self::Unit(_, ty) => *ty, + other => other + } + } + + /// Is this type recursive? pub fn is_recursive_helper( &self, symbols: &mut HashSet, @@ -265,7 +291,7 @@ impl Type { } Self::Poly(params, t) => { - for param in params { + for (param, _) in params { symbols.remove(param); } t.is_recursive_helper(symbols, env) @@ -317,7 +343,9 @@ impl Type { Ok(false) } Self::Enum(_) => Ok(false), - Self::None + + Self::ConstParam(_) + | Self::None | Self::Int | Self::Float | Self::Cell @@ -340,6 +368,7 @@ impl Type { result } + /// Strip the template arguments to get the inner type pub fn strip_template(&self, env: &Env) -> Self { debug!("strip_template: {}", self); match self { @@ -353,18 +382,22 @@ impl Type { self.clone() } } + Self::Pointer(mutability, ty) => Self::Pointer(*mutability, ty.strip_template(env).into()), _ => self.clone(), } } + /// Is this a polymorphic function? pub fn is_poly(&self) -> bool { matches!(self, Self::Poly(_, _)) } + /// Get the template arguments for the monomorph (this type) of some polymorphic base type. + /// This will match the symbols in the template against the monomorph. pub fn get_monomorph_template_args( &self, template: &Self, - matched_symbols: &mut HashMap, + matched_symbols: &mut HashMap)>, param_symbols: &HashSet, env: &Env, ) -> Result<(), Error> { @@ -422,8 +455,21 @@ impl Type { } } - (Self::Array(inner1, _), Self::Array(inner2, _)) => { + (Self::Array(inner1, cexpr1), Self::Array(inner2, cexpr2)) => { inner1.get_monomorph_template_args(inner2, matched_symbols, param_symbols, env)?; + + let ty1 = match &**cexpr1 { + ConstExpr::Symbol(name) => Type::Symbol(name.clone()), + ConstExpr::Type(ty) => ty.clone(), + otherwise => Type::ConstParam(otherwise.clone().into()) + }; + let ty2 = match &**cexpr2 { + ConstExpr::Symbol(name) => Type::Symbol(name.clone()), + ConstExpr::Type(ty) => ty.clone(), + _ => return Ok(()) + }; + + ty1.get_monomorph_template_args(&ty2, matched_symbols, param_symbols, env)? } (Self::Pointer(_, inner1), Self::Pointer(_, inner2)) => { @@ -454,18 +500,18 @@ impl Type { } (Self::Apply(template, args), Self::Poly(params, ret)) => { - for (param, arg) in params.iter().zip(args.iter()) { + for ((param, expected), arg) in params.iter().zip(args.iter()) { // ret.get_monomorph_template_args(arg, symbols, env)?; - matched_symbols.insert(param.clone(), arg.clone()); + matched_symbols.insert(param.clone(), (arg.clone(), expected.clone())); debug!("Found match {}: {}", param, arg); } template.get_monomorph_template_args(ret, matched_symbols, param_symbols, env)?; } (Self::Apply(template, args), other) => { - if let Ok(Self::Poly(params, ret)) = template.simplify_until_poly(env) { + if let Ok(Self::Poly(params, ret)) = template.simplify_until_poly(env, false) { let mut ret = *ret.clone(); - for (param, arg) in params.iter().zip(args.iter()) { + for ((param, _), arg) in params.iter().zip(args.iter()) { ret = ret.substitute(param, arg); } @@ -475,7 +521,7 @@ impl Type { (other, Self::Symbol(name)) => { if param_symbols.contains(name) { debug!("Found match {}: {}", name, other); - matched_symbols.insert(name.clone(), other.clone()); + matched_symbols.insert(name.clone(), (other.clone(), None)); } else if let Some(t) = env.get_type(name) { debug!("Symbol {name} is {t}"); other.get_monomorph_template_args(t, matched_symbols, param_symbols, env)?; @@ -490,7 +536,7 @@ impl Type { (a, b) => { if a != b { - error!( + debug!( "get_monomorph_template_args: Couldn't match {} to {}", self, template ); @@ -501,12 +547,16 @@ impl Type { Ok(()) } + /// Is this type a monomorph of a given template type? pub fn is_monomorph_of(&self, template: &Self, env: &Env) -> Result { - match (self, template) { - (Self::Apply(template1, _), template2) => template1.equals(template2, env), + debug!("{self} is mono of {template}?"); + let result = match (self, template) { + (Self::Apply(template1, _), template2) => { + template1.equals(template2, env) + }, (concrete, Self::Poly(params, result)) => { let mut result = *result.clone(); - for param in params { + for (param, _) in params { result = result.substitute(param, &Type::Any); } concrete.equals(&result, env) @@ -525,22 +575,37 @@ impl Type { Ok(false) } + (Self::Pointer(mut1, ty1), Self::Pointer(mut2, ty2)) => { + Ok(mut1 == mut2 && ty1.is_monomorph_of(ty2, env)?) + } + + (Self::Array(elem1, len1), Self::Array(elem2, len2)) => { + return Ok(elem1.is_monomorph_of(elem2, env)? && len1.get_type(env)?.equals(&len2.get_type(env)?, env)?) + } + + (Self::ConstParam(cexpr), other) => cexpr.get_type(env)?.equals(other, env), + _ => Ok(false), + }; + if result.clone().is_ok_and(|x| x) { + debug!("{self} is monomorph of {template}"); + } else { + debug!("{self} is NOT monomorph of {template}"); } + result } + /// Add monomorphized methods for a given monomorph of a template type with methods. pub fn add_monomorphized_associated_consts(&self, env: &Env) -> Result<(), Error> { - // warn!("add_monomorphized_associated_consts: Adding monomorphized associated consts for {}", self); match self.clone() { Self::Apply(template, args) => { let simplified_args = args .iter() - .map(|t| t.simplify_until_concrete(env)) + .map(|t| t.simplify_until_concrete(env, false)) .collect::, _>>()?; let mut mono_ty = Self::Apply(template.clone(), simplified_args.clone()); - mono_ty = mono_ty.simplify_until_concrete(env)?; - // warn!("add_monomorphized_associated_consts: Adding monomorphized associated consts for {self} to {}", mono_ty); + mono_ty = mono_ty.simplify_until_concrete(env, false)?; env.add_monomorphized_associated_consts(*template, mono_ty, simplified_args)?; } @@ -593,6 +658,7 @@ impl Type { // t.add_monomorphized_associated_consts(env)?; } Self::Let(_, _, _) + | Self::ConstParam(_) | Self::Any | Self::None | Self::Never @@ -606,26 +672,16 @@ impl Type { Ok(()) } - pub fn get_template_params(&self, env: &Env) -> Vec { + /// Get the template parameters for this template type. + pub fn get_template_params(&self, env: &Env) -> Vec<(String, Option)> { debug!("get_template_params: {}", self); - match self.simplify_until_poly(env) { + match self.simplify_until_poly(env, false) { Ok(Self::Poly(params, _)) => { - debug!( - "get_template_params: {} params: {}", - self, - params.join(", ") - ); params.clone() } Ok(Self::Symbol(name)) => { if let Some(t) = env.get_type(&name) { - let result = t.get_template_params(env); - debug!( - "get_template_params: {} params: {}", - name, - result.join(", ") - ); - result + t.get_template_params(env) } else { debug!("get_template_params: Couldn't find type {}", name); vec![] @@ -641,6 +697,7 @@ impl Type { } } + /// Apply this template type with some type arguments. pub fn apply(&self, args: Vec) -> Self { Self::Apply(Box::new(self.clone()), args) } @@ -663,6 +720,7 @@ impl Type { | Self::Bool | Self::Any | Self::Never + | Self::ConstParam(_) | Self::Enum(_) | Self::Type(_) => true, Self::Unit(_, t) => t.is_simple(), @@ -682,7 +740,7 @@ impl Type { return false; } let mut ret = *ret.clone(); - for (param, arg) in params.iter().zip(args.iter()) { + for ((param, _), arg) in params.iter().zip(args.iter()) { if !arg.is_simple() { return false; } @@ -699,9 +757,14 @@ impl Type { } } + /// Is this type simplified enough to get information about what the + /// outer type is? Is it a tuple, a struct, etc? + /// + /// Symbols and polymorphic types do not satisfy this condition. pub fn is_concrete(&self) -> bool { match self { Self::Poly(_, _) | Self::Symbol(_) | Self::Apply(_, _) | Self::Let(_, _, _) => false, + Self::None | Self::Int | Self::Float @@ -710,6 +773,7 @@ impl Type { | Self::Bool | Self::Any | Self::Never + | Self::ConstParam(_) | Self::Enum(_) | Self::EnumUnion(_) | Self::Struct(_) @@ -717,8 +781,8 @@ impl Type { | Self::Proc(_, _) | Self::Tuple(_) | Self::Unit(_, _) - | Self::Type(_) | Self::Array(_, _) + | Self::Type(_) | Self::Pointer(_, _) => true, } } @@ -735,7 +799,9 @@ impl Type { | Self::Any | Self::Never | Self::Enum(_) + | Self::ConstParam(_) | Self::Type(_) => true, + Self::Unit(_, t) => t.is_atomic(), Self::Tuple(inner) => inner.iter().all(|t| t.is_atomic()), Self::Array(inner, expr) => inner.is_atomic() && matches!(**expr, ConstExpr::Int(_)), @@ -743,15 +809,14 @@ impl Type { Self::Pointer(_, inner) => inner.is_atomic(), Self::Struct(inner) => inner.iter().all(|(_, t)| t.is_atomic()), Self::EnumUnion(inner) => inner.iter().all(|(_, t)| t.is_atomic()), - // Self::Poly(_, _) | Self::Symbol(_) | Self::Apply(_, _) => false, - // Self::Let(_, _, ret) => ret.is_atomic(), + _ => false, } } /// Is first argument of function a reference? pub fn is_self_param_reference(&self, env: &Env) -> Result { - Ok(match self.simplify_until_concrete(env)? { + Ok(match self.simplify_until_concrete(env, false)? { Self::Proc(args, _) => { matches!(args.first(), Some(Self::Pointer(_, _))) } @@ -761,7 +826,7 @@ impl Type { /// Get the first argument's mutability (if it is a pointer) pub fn get_self_param_mutability(&self, env: &Env) -> Option { - match self.simplify_until_concrete(env) { + match self.simplify_until_concrete(env, false) { Ok(Self::Proc(args, _)) => { if let Some(Self::Pointer(mutability, _)) = args.first() { Some(*mutability) @@ -774,7 +839,7 @@ impl Type { Ok(Self::Apply(template, args)) => { if let Self::Poly(ref params, ref inner) = *template { let mut inner = *inner.clone(); - for (param, arg) in params.iter().zip(args.iter()) { + for ((param, _), arg) in params.iter().zip(args.iter()) { inner = inner.substitute(param, arg); } inner.get_self_param_mutability(env) @@ -790,9 +855,10 @@ impl Type { /// Simplify until the type passes the type checker. pub fn simplify_until_type_checks(&self, env: &Env) -> Result { self.clone() - .simplify_until_matches(env, Type::Any, |t, env| t.type_check(env).map(|_| true)) + .simplify_until_matches(env, Type::Any, |t, env| t.type_check(env).map(|_| true), true) } + /// Does this type possibly have some members/fields? fn possibly_has_members(&self) -> bool { if matches!( self, @@ -809,10 +875,10 @@ impl Type { } /// Simplify a type until you can get its members. - pub fn simplify_until_has_members(&self, env: &Env) -> Result { + pub fn simplify_until_has_members(&self, env: &Env, checked: bool) -> Result { let result = self .clone() - .simplify_until_matches(env, Type::Any, |t, _| Ok(t.possibly_has_members())); + .simplify_until_matches(env, Type::Any, |t, _| Ok(t.possibly_has_members()), checked); if result.is_err() { warn!("Couldn't simplify {} to a type with members", self); @@ -821,6 +887,7 @@ impl Type { result } + /// Is this a union type? fn is_union(&self) -> bool { if matches!(self, Self::Union(_) | Self::EnumUnion(_)) { return true; @@ -834,16 +901,17 @@ impl Type { } /// Simplify a type until it's a union. - pub fn simplify_until_union(&self, env: &Env) -> Result { + pub fn simplify_until_union(&self, env: &Env, checked: bool) -> Result { let result = self .clone() - .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_union())); + .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_union()), checked); if result.is_err() { debug!("Couldn't simplify {} to a union", self); } result } + /// Does this type have enum variants? fn has_variants(&self) -> bool { if matches!(self, Self::Enum(_) | Self::EnumUnion(_)) { return true; @@ -857,16 +925,17 @@ impl Type { } /// Simplify a type until you can get its variants. - pub fn simplify_until_has_variants(&self, env: &Env) -> Result { + pub fn simplify_until_has_variants(&self, env: &Env, checked: bool) -> Result { let result = self .clone() - .simplify_until_matches(env, Type::Enum(vec![]), |t, _| Ok(t.has_variants())); + .simplify_until_matches(env, Type::Enum(vec![]), |t, _| Ok(t.has_variants()), checked); if result.is_err() { debug!("Couldn't simplify {} to a type with variants", self); } result } + /// Is this type polymorphic? fn is_polymorphic(&self) -> bool { if matches!(self, Self::Poly(_, _)) { return true; @@ -879,19 +948,19 @@ impl Type { false } - pub fn simplify_until_atomic(&self, env: &Env) -> Result { + pub fn simplify_until_atomic(&self, env: &Env, checked: bool) -> Result { let result = self .clone() - .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_atomic())); + .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_atomic()), checked); if result.is_err() { debug!("Couldn't simplify {} to an atomic type", self); } result } - pub fn simplify_until_simple(&self, env: &Env) -> Result { + pub fn simplify_until_simple(&self, env: &Env, checked: bool) -> Result { let result = self .clone() - .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_simple())); + .simplify_until_matches(env, Type::Any, |t, _| Ok(t.is_simple()), checked); if result.is_err() { debug!("Couldn't simplify {} to a simple type", self); } @@ -899,11 +968,12 @@ impl Type { } /// Simplify until the type is a polymorphic type. - pub fn simplify_until_poly(&self, env: &Env) -> Result { + pub fn simplify_until_poly(&self, env: &Env, checked: bool) -> Result { let result = self.clone().simplify_until_matches( env, Type::Poly(vec![], Box::new(Type::Any)), |t, _| Ok(t.is_polymorphic()), + checked ); if result.is_err() { debug!("Couldn't simplify {} to a polymorphic type", self); @@ -912,16 +982,75 @@ impl Type { } /// Simplify until the type is concrete. - pub fn simplify_until_concrete(&self, env: &Env) -> Result { + pub fn simplify_until_concrete(&self, env: &Env, checked: bool) -> Result { let result = self .clone() - .simplify_until_matches(env, Type::Any, |t, _env| Ok(t.is_concrete())); + .simplify_until_matches(env, Type::Any, |t, _env| Ok(t.is_concrete()), checked); if result.is_err() { debug!("Couldn't simplify {} to a concrete type", self); } + result } + /// Simplify until the type is concrete. + pub fn simplify_until_const_param(&self, env: &Env, _checked: bool) -> Result { + let mut simplified = self.clone(); + for _ in 0..3 { + if let Self::ConstParam(cexpr) = simplified { + return Ok(*cexpr); + } + simplified = simplified.simplify(env)?; + if let Self::ConstParam(cexpr) = simplified { + return Ok(*cexpr); + } + simplified = match simplified { + Self::Tuple(items) => { + let simple_items = items + .into_iter() + .map(|t| t.simplify(env)) + .collect::, Error>>()?; + + if simple_items.iter().all(Self::is_const_param) { + Self::ConstParam(ConstExpr::Tuple(simple_items + .into_iter() + .map(|t| Ok(match t { + Type::ConstParam(cexpr) => cexpr.eval(env)?, + _ => unreachable!() + })) + .collect::>()?).into()) + } else { + Self::Tuple(simple_items) + } + } + Self::Struct(fields) => { + let simple_fields = fields + .into_iter() + .map(|(name, t)| Ok((name, t.simplify(env)?))) + .collect::, Error>>()?; + + if simple_fields.iter().map(|(_x, t)| t).all(Self::is_const_param) { + Self::ConstParam(ConstExpr::Struct(simple_fields + .into_iter() + .map(|(name, t)| Ok(match t { + Type::ConstParam(cexpr) => (name, cexpr.eval(env)?), + _ => unreachable!() + })) + .collect::>()?).into()) + } else { + Self::Struct(simple_fields) + } + } + other => other + }; + } + + match simplified { + Type::ConstParam(cexpr) => Ok(*cexpr), + result => panic!("Unexpected {result}") + } + } + /// Simplify an expression until it matches a given function which "approves" of a type. /// This will perform template applications to simplify the type if possible as well. /// @@ -932,6 +1061,7 @@ impl Type { env: &Env, expected: Self, f: impl Fn(&Self, &Env) -> Result, + checked: bool ) -> Result { let mut simplified = self; // for _ in 0..Self::SIMPLIFY_RECURSION_LIMIT { @@ -939,7 +1069,7 @@ impl Type { if f(&simplified, env)? || simplified.is_atomic() { return Ok(simplified); } - simplified = simplified.perform_template_applications(env, &mut HashMap::new())? + simplified = simplified.perform_template_applications(env, &mut HashMap::new(), checked)? } Err(Error::CouldntSimplify(simplified, expected)) } @@ -970,7 +1100,7 @@ impl Type { } Self::Type(t) => t.contains_symbol(name), Self::Poly(ty_params, template) => { - if ty_params.contains(&name.to_string()) { + if ty_params.iter().map(|x| x.0.clone()).collect::>().contains(&name.to_string()) { // This type variable is shadowed by a template variable. false } else { @@ -990,6 +1120,12 @@ impl Type { t.contains_symbol(name) || (typename != name && ret.contains_symbol(name)) } Self::Symbol(typename) => typename == name, + Self::ConstParam(cexpr) => { + match &**cexpr { + ConstExpr::Symbol(const_name) | ConstExpr::Type(Type::Symbol(const_name)) => name == const_name, + _ => false + } + } Self::None | Self::Never | Self::Any @@ -1016,7 +1152,7 @@ impl Type { /// Substitute all occurences of a symbol with another type. /// This will not traverse into let-bindings when the symbol is overshadowed. pub fn substitute(&self, name: &str, substitution: &Self) -> Self { - match self { + let result = match self { Self::Type(t) => Self::Type(Box::new(t.substitute(name, substitution))), Self::Let(typename, binding, ret) => Self::Let( typename.clone(), @@ -1036,13 +1172,13 @@ impl Type { }, ), Self::Poly(ty_params, template) => { - if ty_params.contains(&name.to_string()) { + if ty_params.iter().map(|x| x.0.clone()).collect::>().contains(&name.to_string()) { // This type variable is shadowed by a template variable. self.clone() } else { // Does the inner symbol use this type variable? Self::Poly( - ty_params.clone(), + ty_params.iter().map(|(x, ty)| (x.clone(), ty.as_ref().map(|ty| ty.substitute(name, substitution)))).collect(), template.substitute(name, substitution).into(), ) } @@ -1064,6 +1200,11 @@ impl Type { unit_name.clone(), Box::new(inner.substitute(name, substitution)), ), + Self::ConstParam(cexpr) => { + let mut cexpr = cexpr.clone(); + cexpr.substitute(name, substitution); + Self::ConstParam(cexpr) + }, Self::None | Self::Never | Self::Any @@ -1079,10 +1220,14 @@ impl Type { .map(|field_t| field_t.substitute(name, substitution)) .collect(), ), - Self::Array(item_t, size) => Self::Array( - Box::new(item_t.substitute(name, substitution)), - size.clone(), - ), + Self::Array(item_t, size) => { + let mut size = size.clone(); + size.substitute(name, substitution); + Self::Array( + Box::new(item_t.substitute(name, substitution)), + size, + ) + }, Self::Struct(fields) => Self::Struct( fields .iter() @@ -1116,7 +1261,8 @@ impl Type { Self::Pointer(mutability, ptr) => { Self::Pointer(*mutability, Box::new(ptr.substitute(name, substitution))) } - } + }; + result } /// Does this type have an element type matching the supplied type? @@ -1139,17 +1285,12 @@ impl Type { /// For all cases right now, a decay does nothing; the representations of the types /// in the compiler are the same for all types of decay. pub fn can_decay_to(&self, desired: &Self, env: &Env) -> Result { - trace!("Checking if {} can decay to {}", self, desired); + // trace!("Checking if {} can decay to {}", self, desired); if self.equals(desired, env)? { return Ok(true); } - // if !self.is_simple() || !desired.is_simple() { - // return Ok(false); - // } - match (self, desired) { - // (Self::Unit(_, inner), _) => inner.can_decay_to(desired, env), (Self::Unit(name1, t1), Self::Unit(name2, t2)) => { if name1 == name2 { t1.can_decay_to(t2, env) @@ -1193,6 +1334,8 @@ impl Type { return Ok(true); } + debug!("Could not decay {self} into {desired}"); + Ok(false) } @@ -1214,10 +1357,10 @@ impl Type { } // Can an array decay to another array? - (Self::Array(found_elem_ty, _), Self::Array(desired_elem_ty, _)) => { + (Self::Array(found_elem_ty, found_len), Self::Array(desired_elem_ty, expected_len)) => { // Check if the element types can decay, and if the sizes are equal. if found_elem_ty.can_decay_to(desired_elem_ty, env)? - && self.get_size(env)? == desired.get_size(env)? + && found_len.clone().eval(env)?.equals(&expected_len.clone().eval(env)?, env) { trace!("{} can decay to {}", self, desired); return Ok(true); @@ -1225,7 +1368,7 @@ impl Type { // Check if the element types are compatible, and if the sizes are equal. if found_elem_ty.has_element_type(desired_elem_ty, env)? - && self.get_size(env)? == desired.get_size(env)? + && found_len.clone().eval(env)?.equals(&expected_len.clone().eval(env)?, env) { trace!("{} can decay to {}", self, desired); return Ok(true); @@ -1258,23 +1401,6 @@ impl Type { trace!("{} can decay to {}", self, desired); Ok(true) } - - // (Type::Apply(f, args), other) => { - // match *f.clone() { - // Type::Poly(params, template) => { - // let mut template = *template.clone(); - // for (param, arg) in params.iter().zip(args.iter()) { - // template = template.substitute(param, arg); - // } - // template.can_decay_to(other, env) - // } - - // } - // // let mut f = f.clone(); - // // for arg in args { - // // f = f.substitute(, substitution) - // // } - // } (Type::Cell, Type::Int) | (Type::Int, Type::Cell) => Ok(true), (a, b) => a.equals(b, env), @@ -1308,6 +1434,8 @@ impl Type { } let result = match (self, other) { + (Self::ConstParam(a), Self::ConstParam(b)) => Ok(a.equals(b, env)), + (Self::Let(name, t, ret), other) | (other, Self::Let(name, t, ret)) => { let mut new_env = env.clone(); new_env.define_type(name, *t.clone()); @@ -1429,6 +1557,7 @@ impl Type { &self, env: &Env, previous_applications: &mut HashMap<(Type, Vec), Type>, + checked: bool, ) -> Result { let _before = self.to_string(); trace!("Performing template applications on {}", self); @@ -1439,10 +1568,10 @@ impl Type { Ok(match self.clone().simplify(env)? { Self::Apply(poly, ty_args) => { let pair = ( - poly.perform_template_applications(env, previous_applications)?, + poly.perform_template_applications(env, previous_applications, checked)?, ty_args .into_iter() - .map(|t| t.perform_template_applications(env, previous_applications)) + .map(|t| t.perform_template_applications(env, previous_applications, checked)) .collect::, _>>()?, ); if let Some(t) = previous_applications.get(&pair) { @@ -1454,16 +1583,46 @@ impl Type { Self::Poly(params, mono_ty) => { let _poly = Self::Poly(params.clone(), mono_ty.clone()); let mut mono_ty = *mono_ty; - for (param, ty_arg) in params.iter().zip(ty_args.iter()) { - mono_ty = mono_ty.substitute(param, ty_arg); + if !checked { + for ((param, _expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) { + mono_ty = mono_ty.substitute(param, ty_arg); + } + } else { + let mut new_env = env.clone(); + for ((param, _expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) { + new_env.define_type(param, ty_arg.clone()); + } + for ((param, expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) { + if let Some(expected_ty) = expected_ty { + if !expected_ty.equals(ty_arg, &new_env)? && !matches!(ty_arg, Type::Unit(name, inner) if param == name || **inner == Type::None) { + return Err(Error::MismatchedTypes { expected: expected_ty.clone(), found: ty_arg.clone(), expr: Expr::ConstExpr(self.clone().into()) }) + } + } + mono_ty = mono_ty.substitute(param, ty_arg); + } } mono_ty } Self::Symbol(s) => match env.get_type(s.as_str()).cloned() { Some(Self::Poly(params, mono_ty)) => { let mut mono_ty = *mono_ty; - for (param, ty_arg) in params.iter().zip(ty_args.iter()) { - mono_ty = mono_ty.substitute(param, ty_arg); + if !checked { + for ((param, _expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) { + mono_ty = mono_ty.substitute(param, ty_arg); + } + } else { + let mut new_env = env.clone(); + for ((param, _expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) { + new_env.define_type(param, ty_arg.clone()); + } + for ((param, expected_ty), ty_arg) in params.iter().zip(ty_args.iter()) { + if let Some(expected_ty) = expected_ty { + if !expected_ty.equals(ty_arg, &new_env)? && !matches!(ty_arg, Type::Unit(name, inner) if param == name || **inner == Type::None) { + return Err(Error::MismatchedTypes { expected: expected_ty.clone(), found: ty_arg.clone(), expr: Expr::ConstExpr(self.clone().into()) }) + } + } + mono_ty = mono_ty.substitute(param, ty_arg); + } } mono_ty } @@ -1476,13 +1635,13 @@ impl Type { } Self::Pointer(mutability, inner) => Self::Pointer( mutability, - Box::new(inner.perform_template_applications(env, previous_applications)?), + Box::new(inner.perform_template_applications(env, previous_applications, checked)?), ), Self::Proc(args, ret) => Self::Proc( args.into_iter() - .map(|t| t.perform_template_applications(env, previous_applications)) + .map(|t| t.perform_template_applications(env, previous_applications, checked)) .collect::, _>>()?, - Box::new(ret.perform_template_applications(env, previous_applications)?), + Box::new(ret.perform_template_applications(env, previous_applications, checked)?), ), Self::Struct(fields) if !self.is_recursive(env)? => Self::Struct( fields @@ -1490,7 +1649,7 @@ impl Type { .map(|(name, t)| { Ok(( name, - t.perform_template_applications(env, previous_applications)?, + t.perform_template_applications(env, previous_applications, checked)?, )) }) .collect::, Error>>()?, @@ -1501,7 +1660,7 @@ impl Type { .map(|(name, t)| { Ok(( name, - t.perform_template_applications(env, previous_applications)?, + t.perform_template_applications(env, previous_applications, checked)?, )) }) .collect::, Error>>()?, @@ -1513,21 +1672,26 @@ impl Type { .map(|(name, t)| { Ok(( name, - t.perform_template_applications(env, previous_applications)?, + t.perform_template_applications(env, previous_applications, checked)?, )) }) .collect::, Error>>()?, ), + Self::Type(ty) if !self.is_recursive(env)? => { + ty.perform_template_applications(env, previous_applications, checked)?; + Self::Type(ty) + } + Self::Tuple(items) if !self.is_recursive(env)? => Self::Tuple( items .into_iter() - .map(|t| t.perform_template_applications(env, previous_applications)) + .map(|t| t.perform_template_applications(env, previous_applications, checked)) .collect::, _>>()?, ), Self::Array(item_t, size) if !self.is_recursive(env)? => Self::Array( - Box::new(item_t.perform_template_applications(env, previous_applications)?), + Box::new(item_t.perform_template_applications(env, previous_applications, checked)?), size, ), @@ -1555,7 +1719,6 @@ impl Type { ); return Ok(false); } - trace!("Checking if {} equals {}", self, other); let i = i + 1; @@ -1685,7 +1848,7 @@ impl Type { } (Self::Array(t1, size1), Self::Array(t2, size2)) => { t1.equals_checked(t2, compared_symbols, env, i)? - && size1.clone().as_int(env)? == size2.clone().as_int(env)? + && size1.clone().eval(env)?.equals(&size2.clone().eval(env)?, env) } (Self::Struct(a), Self::Struct(b)) => { if a.len() != b.len() { @@ -1752,7 +1915,21 @@ impl Type { // Create a new environment. let mut new_env = env.clone(); - for (name1, name2) in ty_params1.iter().zip(ty_params2.iter()) { + for ((name1, _ty1), (name2, _ty2)) in ty_params1.iter().zip(ty_params2.iter()) { + // match (ty1, ty2) { + // (Some(ty1), Some(ty2)) => { + // if !ty1.equals_checked(&ty2, compared_symbols, &new_env, i)? { + // return Err(Error::MismatchedTypes { expected: ty1.clone(), found: ty2.clone(), expr: Expr::ConstExpr(self.clone().into()) }) + // } + // } + // (None, None) => {} + // (Some(ty1), None) => { + // return Err(Error::MismatchedTypes { expected: ty1.clone(), found: Self::Type(Type::Any.into()), expr: Expr::ConstExpr(self.clone().into()) }) + // } + // (None, Some(ty2)) => { + // return Err(Error::UnexpectedConstParam { found: ty2.clone(), expr: Expr::ConstExpr(self.clone().into()) }) + // } + // } // In the new environment, bind the two type parameters to the same type. let combined_name = format!("{name1}+{name2}"); let combined_ty = Self::Unit(combined_name, Box::new(Type::Any)); @@ -1783,13 +1960,13 @@ impl Type { true } else if let Self::Poly(ty_params, template) = poly1.clone().simplify(env)? { let mut template = *template.clone(); - for (param, arg) in ty_params.iter().zip(ty_args1.iter()) { + for ((param, _), arg) in ty_params.iter().zip(ty_args1.iter()) { template = template.substitute(param, arg); } template.equals_checked(other, compared_symbols, env, i)? } else if let Self::Poly(ty_params, template) = poly2.clone().simplify(env)? { let mut template = *template.clone(); - for (param, arg) in ty_params.iter().zip(ty_args2.iter()) { + for ((param, _), arg) in ty_params.iter().zip(ty_args2.iter()) { template = template.substitute(param, arg); } template.equals_checked(other, compared_symbols, env, i)? @@ -1808,12 +1985,16 @@ impl Type { (Self::Apply(poly, ty_args), b) | (b, Self::Apply(poly, ty_args)) => { Self::Apply(poly.clone(), ty_args.clone()) - .simplify_until_concrete(env)? + .simplify_until_concrete(env, false)? .equals_checked(b, compared_symbols, env, i)? } - _ => { - // trace!("{} is not equal to {}", a, b); + (Self::ConstParam(a), Self::ConstParam(b)) => a == b, + (Self::ConstParam(cexpr), other) | (other, Self::ConstParam(cexpr)) => { + cexpr.get_type(env)?.equals_checked(other, compared_symbols, env, i)? + }, + (_a, _b) => { + // error!("{} is not equal to {}", a, b); false } }) @@ -1828,7 +2009,7 @@ impl Type { expr: &Expr, env: &Env, ) -> Result<(Type, usize), Error> { - trace!("Getting offset of member {member} in expression {self} in the environment {env}"); + debug!("Getting offset of member {member} in expression {self} in the environment {env}"); match self { Type::Pointer(_, t) => t.get_member_offset(member, expr, env), Type::Struct(members) => { @@ -1887,7 +2068,7 @@ impl Type { Type::Unit(_unit_name, t) => t.get_member_offset(member, expr, env), Type::Apply(_, _) | Type::Poly(_, _) => { - let t = self.simplify_until_concrete(env)?; + let t = self.simplify_until_concrete(env, false)?; t.get_member_offset(member, expr, env) } @@ -1900,6 +2081,14 @@ impl Type { } } + Type::Type(ty) => { + if ty.is_const_param() { + ty.simplify_until_const_param(env, false)?.get_type(env)?.get_member_offset(member, expr, env) + } else { + Err(Error::MemberNotFound(expr.clone(), member.clone())) + } + } + _ => Err(Error::MemberNotFound(expr.clone(), member.clone())), } } @@ -1913,12 +2102,19 @@ impl Type { trace!("Typechecking member \"{member}\" of {expr} in {env}"); match self { Type::Type(ty) => { - let name = member.clone().as_symbol(env)?; - - if env.has_associated_const(ty, &name) { - Ok(()) + if ty.type_check_member(member, expr, env).is_ok() { + return Ok(()) + } + if ty.is_const_param() { + ty.simplify_until_const_param(env, true)?.get_type(env)?.type_check_member(member, expr, env) } else { - Err(Error::MemberNotFound(expr.clone(), member.clone())) + let name = member.clone().as_symbol(env)?; + + if env.has_associated_const(ty, &name) { + Ok(()) + } else { + Err(Error::MemberNotFound(expr.clone(), member.clone())) + } } } @@ -1994,7 +2190,7 @@ impl Type { } Type::Apply(_, _) | Type::Poly(_, _) => { - let t = self.simplify_until_concrete(env)?; + let t = self.simplify_until_concrete(env, true)?; trace!("Simplified {self} to {t}"); t.type_check_member(member, expr, env) } @@ -2034,7 +2230,14 @@ impl Simplify for Type { let _s = self.to_string(); let result = match self { - Self::Type(t) => Self::Type(t), + Self::Type(t) => { + if t.is_const_param() { + Self::ConstParam(t.simplify_until_const_param(env, false)?.into()) + } else { + Self::Type(t.into()) + } + }, + Self::ConstParam(cexpr) => Self::ConstParam(cexpr.eval(env)?.into()), Self::None | Self::Never @@ -2044,8 +2247,15 @@ impl Simplify for Type { | Self::Char | Self::Bool | Self::Cell - | Self::Enum(_) - | Self::Poly(_, _) => self.clone(), + | Self::Enum(_) => self.clone(), + Self::Poly(mut ty_params, body) => { + for (_name, ty) in &mut ty_params { + if let Some(ty) = ty { + *ty = ty.clone().simplify_checked(env, i)?; + } + } + Self::Poly(ty_params, body) + } Self::Pointer(mutability, inner) => { Self::Pointer(mutability, Box::new(inner.simplify_checked(env, i)?)) } @@ -2077,12 +2287,13 @@ impl Simplify for Type { Self::Unit(unit_name, t) => { Self::Unit(unit_name, Box::new(t.simplify_checked(env, i)?)) - // self } Self::Symbol(ref name) => { if let Some(t) = env.get_type(name) { t.clone() + } else if let Some(cexpr) = env.get_const(name) { + Type::ConstParam(cexpr.clone().into()) } else { self.clone() } @@ -2095,22 +2306,47 @@ impl Simplify for Type { Box::new(ret.simplify_checked(env, i)?), ), - Self::Tuple(items) => Self::Tuple( - items - .into_iter() - .flat_map(|t| t.simplify_checked(env, i)) - .collect(), - ), Self::Array(inner, size) => Self::Array( Box::new(inner.simplify_checked(env, i)?), Box::new(size.eval(env)?), ), - Self::Struct(fields) => Self::Struct( - fields + + Self::Tuple(items) => { + let simple_items = items .into_iter() - .map(|(k, t)| Ok((k, t.simplify_checked(env, i)?))) - .collect::, Error>>()?, - ), + .map(|t| t.simplify_checked(env, i)) + .collect::, Error>>()?; + + if simple_items.iter().all(Self::is_const_param) { + Self::ConstParam(ConstExpr::Tuple(simple_items + .into_iter() + .map(|t| Ok(match t { + Type::ConstParam(cexpr) => cexpr.eval(env)?, + _ => unreachable!() + })) + .collect::>()?).into()) + } else { + Self::Tuple(simple_items) + } + } + Self::Struct(fields) => { + let simple_fields = fields + .into_iter() + .map(|(name, t)| Ok((name, t.simplify_checked(env, i)?))) + .collect::, Error>>()?; + + if simple_fields.iter().map(|(_x, t)| t).all(Self::is_const_param) { + Self::ConstParam(ConstExpr::Struct(simple_fields + .into_iter() + .map(|(name, t)| Ok(match t { + Type::ConstParam(cexpr) => (name, cexpr.eval(env)?), + _ => unreachable!() + })) + .collect::>()?).into()) + } else { + Self::Struct(simple_fields) + } + } Self::Union(types) => Self::Union( types .into_iter() @@ -2125,21 +2361,6 @@ impl Simplify for Type { ), Self::Apply(poly, ty_args) => { - // let poly_clone = poly.clone(); - // match *poly { - // Self::Poly(params, mut result) => { - // for (param, arg) in params.iter().zip(ty_args.iter()) { - // *result = result.substitute(param, arg); - // } - // // *result = result.simplify_checked(env, i)?; - - // // Add mono type to environment - // env.add_monomorphized_associated_consts(*poly_clone, *result.clone(), ty_args)?; - // *result - // } - // _ => Self::Apply(Box::new(poly.simplify_checked(env, i)?), ty_args) - // } - Self::Apply(Box::new(poly.simplify_checked(env, i)?), ty_args) } }; @@ -2150,7 +2371,8 @@ impl Simplify for Type { impl fmt::Display for Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Self::Type(t) => write!(f, "{t}"), + Self::ConstParam(t) => write!(f, "const param {t}"), + Self::Type(t) => write!(f, "type {t}"), Self::Any => write!(f, "Any"), Self::Never => write!(f, "Never"), Self::Pointer(mutability, ty) => { @@ -2169,8 +2391,11 @@ impl fmt::Display for Type { Self::Array(ty, len) => write!(f, "[{ty} * {len}]"), Self::Poly(ty_params, template) => { write!(f, "(")?; - for (i, param) in ty_params.iter().enumerate() { + for (i, (param, ty)) in ty_params.iter().enumerate() { write!(f, "{param}")?; + if let Some(ty) = ty { + write!(f, ": {ty}")?; + } if i < ty_params.len() - 1 { write!(f, ", ")? } @@ -2355,6 +2580,10 @@ impl std::hash::Hash for Type { state.write_u8(21); t.hash(state); } + Self::ConstParam(cexpr) => { + state.write_u8(22); + cexpr.hash(state); + } } } } diff --git a/src/lir/types/size.rs b/src/lir/types/size.rs index 8976a68c..b3e4eaca 100644 --- a/src/lir/types/size.rs +++ b/src/lir/types/size.rs @@ -58,7 +58,14 @@ impl GetSize for Type { }); } + if self.is_const_param() { + let cexpr = self.clone().simplify_until_const_param(env, false)?; + return cexpr.get_size_checked(env, i) + } + let result = match self { + Self::ConstParam(cexpr) => cexpr.get_size_checked(env, i)?, + // None or Never are not real types, so they have no size. // They are not represented with data. They have zero size. Self::Type(_) | Self::None | Self::Never => 0, @@ -164,7 +171,7 @@ impl GetSize for Type { return Ok(size); } - let result = self.clone().simplify_until_concrete(env)?; + let result = self.clone().simplify_until_concrete(env, false)?; result.get_size_checked(env, i)? } diff --git a/src/vm/std.rs b/src/vm/std.rs index dda758a5..08ae3c30 100644 --- a/src/vm/std.rs +++ b/src/vm/std.rs @@ -83,7 +83,6 @@ impl VirtualMachineProgram for StandardProgram { self.0.pop(); self.op(CoreOp::Set(vec![(n[0] >= 0) as i64])) } - (_, op) => { self.0.push(StandardOp::CoreOp(op)); } diff --git a/tests/c_target.rs b/tests/c_target.rs index 03a7b7dc..ca823697 100644 --- a/tests/c_target.rs +++ b/tests/c_target.rs @@ -25,7 +25,7 @@ fn test_c_target_frontend_examples() { builder.init(); rayon::ThreadPoolBuilder::new() - .num_threads(1) + .num_threads(16) .stack_size(512 * 1024 * 1024) .build_global() .unwrap(); @@ -99,7 +99,7 @@ fn test_c_target_frontend_examples_helper() { if let Some(correct_error) = correct_error { let text = e.to_string(); if text != correct_error { - panic!("{text:?} != {correct_error:?}, error did not match correct error for program {path:?}") + panic!("{text:?} (incorrect) != {correct_error:?} (correct), error did not match correct error for program {path:?}") } else { continue; } diff --git a/tests/examples.rs b/tests/examples.rs index 29e9bcec..a158d4a3 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -109,7 +109,8 @@ fn test_frontend_examples_helper() { if let Some(correct_error) = correct_error { let text = e.to_string(); if text != correct_error { - panic!("{text:?} != {correct_error:?}, error did not match correct error for program {path:?}") + panic!("{text:?} (incorrect) != {correct_error:?} (correct), error did not match correct error for program {path:?}") + // panic!("{text:?} != {correct_error:?}, error did not match correct error for program {path:?}") } else { continue; }