Write to .ll files
This commit is contained in:
parent
4d6ad1bb2c
commit
16cde4377c
16 changed files with 314 additions and 148 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -3,6 +3,8 @@ result*
|
|||
|
||||
*.bc
|
||||
*.ll
|
||||
*.ast
|
||||
|
||||
a.out
|
||||
.direnv
|
||||
|
||||
|
|
116
Cargo.lock
generated
116
Cargo.lock
generated
|
@ -64,12 +64,6 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
@ -154,9 +148,9 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"inkwell",
|
||||
"lalrpop",
|
||||
"lalrpop-util",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -174,6 +168,15 @@ dependencies = [
|
|||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
|
@ -223,26 +226,12 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "inkwell"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/TheDan64/inkwell?branch=master#25b9fc5870370211504e874e7c81dc53573bca79"
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"either",
|
||||
"inkwell_internals",
|
||||
"libc",
|
||||
"llvm-sys",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inkwell_internals"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/TheDan64/inkwell?branch=master#25b9fc5870370211504e874e7c81dc53573bca79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -286,31 +275,12 @@ dependencies = [
|
|||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
|
||||
[[package]]
|
||||
name = "llvm-sys"
|
||||
version = "120.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09b716322964966a62377cf86e64f00ca7043505fdf27bd2ec7d41ae6682d1e7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"regex",
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.7"
|
||||
|
@ -377,15 +347,6 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
|
||||
dependencies = [
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.2"
|
||||
|
@ -496,6 +457,15 @@ version = "0.6.27"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.8"
|
||||
|
@ -508,24 +478,6 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
|
||||
dependencies = [
|
||||
"pest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.10"
|
||||
|
@ -568,6 +520,20 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.7.0"
|
||||
|
@ -623,12 +589,6 @@ dependencies = [
|
|||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.2"
|
||||
|
|
|
@ -7,11 +7,7 @@ edition = "2021"
|
|||
anyhow = "1.0.56"
|
||||
clap = { version = "3.1.8", features = ["derive"] }
|
||||
lalrpop-util = { version = "0.19.7", features = ["lexer"] }
|
||||
|
||||
[dependencies.inkwell]
|
||||
git = "https://github.com/TheDan64/inkwell"
|
||||
branch = "master"
|
||||
features = ["llvm12-0"]
|
||||
tempfile = "3.3.0"
|
||||
|
||||
[build-dependencies]
|
||||
lalrpop = "0.19.7"
|
||||
|
|
17
default.nix
17
default.nix
|
@ -1,6 +1,4 @@
|
|||
{ fenix, makeRustPlatform, lib, nix-gitignore, llvmPkgs, libffi }:
|
||||
|
||||
with llvmPkgs;
|
||||
{ fenix, makeRustPlatform, lib, nix-gitignore, libffi, libgcc }:
|
||||
|
||||
let rustPlatform = makeRustPlatform { inherit (fenix.minimal) cargo rustc; };
|
||||
|
||||
|
@ -8,15 +6,8 @@ in rustPlatform.buildRustPackage {
|
|||
name = "e0";
|
||||
src = nix-gitignore.gitignoreSource [ ./.gitignore ] ./.;
|
||||
|
||||
nativeBuildInputs = [ llvm.dev ];
|
||||
buildInputs = [ libffi llvm ];
|
||||
nativeBuildInputs = [ ];
|
||||
buildInputs = [ libffi ];
|
||||
|
||||
LLVM_SYS_120_PREFIX = "${llvm.dev}";
|
||||
|
||||
cargoLock = {
|
||||
lockFile = ./Cargo.lock;
|
||||
outputHashes = {
|
||||
"inkwell-0.1.0" = "sha256-+ih3SO0n6YmZ/mcf+rLDwPAy/1MEZ/A+tI4pM1pUhvU=";
|
||||
};
|
||||
};
|
||||
cargoLock = { lockFile = ./Cargo.lock; };
|
||||
}
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
fn main() -> int {
|
||||
let x = 5;
|
||||
let x = 25;
|
||||
|
||||
if x < 3 {
|
||||
return 3;
|
||||
} else if x > 10 {
|
||||
if x < 10 {
|
||||
return 10;
|
||||
} else if x > 50 {
|
||||
return 50;
|
||||
} else {
|
||||
return x;
|
||||
if x < 20 {
|
||||
return 20;
|
||||
} else if x > 40 {
|
||||
return 40;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
flake.nix
11
flake.nix
|
@ -12,16 +12,17 @@
|
|||
inherit system;
|
||||
overlays = [ fenix.overlay ];
|
||||
};
|
||||
# https://github.com/NixOS/nixpkgs/issues/148117
|
||||
llvmPkgs = pkgs.pkgsStatic.llvmPackages_12;
|
||||
myPkgs = rec { e0 = pkgs.callPackage ./. { inherit llvmPkgs; }; };
|
||||
myPkgs = rec { e0 = pkgs.callPackage ./. { }; };
|
||||
|
||||
in rec {
|
||||
devShell = pkgs.mkShell {
|
||||
packages = with pkgs; [ llvmPkgs.clangUseLLVM cargo-watch ];
|
||||
packages = with pkgs;
|
||||
with pkgs.llvmPackages_12; [
|
||||
cargo-watch
|
||||
clangUseLLVM
|
||||
];
|
||||
inputsFrom = with myPkgs; [ e0 ];
|
||||
CARGO_UNSTABLE_SPARSE_REGISTRY = "true";
|
||||
LLVM_SYS_120_PREFIX = "${llvmPkgs.llvm.dev}";
|
||||
};
|
||||
|
||||
packages = utils.lib.flattenTree myPkgs;
|
||||
|
|
12
src/ast/cranelift.rs
Normal file
12
src/ast/cranelift.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use anyhow::Result;
|
||||
use cranelift_codegen::Context as ClifContext;
|
||||
|
||||
use super::{Decl, Type};
|
||||
|
||||
pub fn convert(
|
||||
file_name: String,
|
||||
context: &Context,
|
||||
program: Vec<Decl<Type>>,
|
||||
) -> Result<ClifContext> {
|
||||
todo!()
|
||||
}
|
|
@ -6,10 +6,7 @@ use inkwell::{
|
|||
context::Context,
|
||||
module::Module,
|
||||
types::{BasicMetadataTypeEnum, BasicTypeEnum, FunctionType},
|
||||
values::{
|
||||
BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue,
|
||||
IntValue, PointerValue,
|
||||
},
|
||||
values::{BasicValue, BasicValueEnum, FunctionValue, IntValue},
|
||||
IntPredicate,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
pub mod llvm;
|
||||
// pub mod llvm;
|
||||
// pub mod cranelift;
|
||||
pub mod typed;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
41
src/codegen/llvm_ir/expr.rs
Normal file
41
src/codegen/llvm_ir/expr.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use std::io::Write;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::ast::{Expr, ExprKind, Stmt, Type};
|
||||
|
||||
use super::{type_to_llvm, LlvmIrCodegen};
|
||||
|
||||
pub struct ExprLlvm<'a>(String, &'a Expr<Type>);
|
||||
|
||||
impl<'a> ExprLlvm<'a> {
|
||||
pub fn name(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> LlvmIrCodegen<W> {
|
||||
pub(super) fn convert_expr<'a>(
|
||||
&mut self,
|
||||
expr: &'a Expr<Type>,
|
||||
) -> Result<ExprLlvm<'a>> {
|
||||
let expr_id = self.gensym("expr");
|
||||
|
||||
match &expr.kind {
|
||||
ExprKind::Int(n) => {
|
||||
let ty_str = type_to_llvm(&expr.ty);
|
||||
writeln!(self.writer, "%{} = alloca {}", expr_id, ty_str)?;
|
||||
writeln!(
|
||||
self.writer,
|
||||
"store {} {}, {}* %{}",
|
||||
ty_str, n, ty_str, expr_id
|
||||
)?;
|
||||
}
|
||||
ExprKind::Var(_) => todo!(),
|
||||
ExprKind::BinOp(_, _, _) => todo!(),
|
||||
ExprKind::Call(_, _) => todo!(),
|
||||
}
|
||||
|
||||
Ok(ExprLlvm(expr_id, expr))
|
||||
}
|
||||
}
|
19
src/codegen/llvm_ir/if_else.rs
Normal file
19
src/codegen/llvm_ir/if_else.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use std::io::Write;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::ast::{IfElse, Stmt, Type};
|
||||
|
||||
use super::LlvmIrCodegen;
|
||||
|
||||
impl<W: Write> LlvmIrCodegen<W> {
|
||||
pub(super) fn convert_if_else(
|
||||
&mut self,
|
||||
if_else: &IfElse<Type>,
|
||||
) -> Result<()> {
|
||||
// Build condition
|
||||
let cond = self.convert_expr(&if_else.cond);
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
76
src/codegen/llvm_ir/mod.rs
Normal file
76
src/codegen/llvm_ir/mod.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
mod expr;
|
||||
mod if_else;
|
||||
mod stmts;
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::ast::{Decl, Type};
|
||||
use crate::utils::LayeredEnv;
|
||||
|
||||
use super::CodegenBackend;
|
||||
|
||||
pub struct LlvmIrCodegen<W> {
|
||||
ctr: usize,
|
||||
env: LayeredEnv<String, ()>,
|
||||
writer: W,
|
||||
}
|
||||
|
||||
impl<W> LlvmIrCodegen<W> {
|
||||
pub fn new(writer: W) -> Self {
|
||||
let env = LayeredEnv::default();
|
||||
LlvmIrCodegen {
|
||||
ctr: 0,
|
||||
env,
|
||||
writer,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gensym(&mut self, name: impl AsRef<str>) -> String {
|
||||
let ctr = self.ctr;
|
||||
self.ctr += 1;
|
||||
format!("{}.{}", name.as_ref(), ctr)
|
||||
}
|
||||
}
|
||||
|
||||
fn type_to_llvm(ty: &Type) -> String {
|
||||
match ty {
|
||||
Type::Int => String::from("i32"),
|
||||
Type::Bool => String::from("i1"),
|
||||
Type::StructInst(_) => todo!(),
|
||||
Type::Func(_, _) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> CodegenBackend for LlvmIrCodegen<W> {
|
||||
fn convert(&mut self, program: Vec<Decl<Type>>) -> Result<()> {
|
||||
// Convert all functions
|
||||
for func in program.iter().filter_map(|decl| match decl {
|
||||
Decl::Func(v) => Some(v),
|
||||
_ => None,
|
||||
}) {
|
||||
// Write the function header
|
||||
println!("Func type: {:?}", func.ty);
|
||||
let (func_args_ty, ret_ty) = match &func.ty {
|
||||
Type::Func(args, ret) => (args, ret),
|
||||
_ => unreachable!(""),
|
||||
};
|
||||
|
||||
writeln!(
|
||||
self.writer,
|
||||
"define {} @{} () {{",
|
||||
type_to_llvm(ret_ty),
|
||||
func.name
|
||||
)?;
|
||||
let entry_block_name = self.gensym("entry");
|
||||
writeln!(self.writer, "{}:", entry_block_name)?;
|
||||
|
||||
self.convert_stmts(&func.stmts)?;
|
||||
|
||||
writeln!(self.writer, "}}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
42
src/codegen/llvm_ir/stmts.rs
Normal file
42
src/codegen/llvm_ir/stmts.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use std::io::Write;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::ast::{Stmt, Type};
|
||||
|
||||
use super::{type_to_llvm, LlvmIrCodegen};
|
||||
|
||||
impl<W: Write> LlvmIrCodegen<W> {
|
||||
pub(super) fn convert_stmts(
|
||||
&mut self,
|
||||
stmts: impl AsRef<[Stmt<Type>]>,
|
||||
) -> Result<()> {
|
||||
let stmts = stmts.as_ref();
|
||||
|
||||
for stmt in stmts.iter() {
|
||||
match stmt {
|
||||
Stmt::Let(_, _, _) => todo!(),
|
||||
Stmt::Return(expr) => match expr {
|
||||
Some(ret_val) => {
|
||||
let ret_ty = type_to_llvm(&ret_val.ty);
|
||||
let ret_val = self.convert_expr(ret_val)?;
|
||||
let ret_name = self.gensym("ret");
|
||||
writeln!(
|
||||
self.writer,
|
||||
"%{} = load {}, {}* %{}",
|
||||
ret_name,
|
||||
ret_ty,
|
||||
ret_ty,
|
||||
ret_val.name()
|
||||
)?;
|
||||
writeln!(self.writer, "ret {} %{}", ret_ty, ret_name)?;
|
||||
}
|
||||
None => writeln!(self.writer, "ret void")?,
|
||||
},
|
||||
Stmt::IfElse(if_else) => self.convert_if_else(if_else)?,
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
9
src/codegen/mod.rs
Normal file
9
src/codegen/mod.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
pub mod llvm_ir;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::ast::{Decl, Type};
|
||||
|
||||
pub trait CodegenBackend {
|
||||
fn convert(&mut self, program: Vec<Decl<Type>>) -> Result<()>;
|
||||
}
|
26
src/main.rs
26
src/main.rs
|
@ -6,15 +6,17 @@ extern crate anyhow;
|
|||
lalrpop_mod!(parser);
|
||||
|
||||
mod ast;
|
||||
pub mod codegen;
|
||||
mod utils;
|
||||
|
||||
use std::fs::{self, File};
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use inkwell::context::Context;
|
||||
|
||||
use crate::codegen::{llvm_ir::LlvmIrCodegen, CodegenBackend};
|
||||
use crate::parser::ProgramParser;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
|
@ -40,15 +42,27 @@ fn main() -> Result<()> {
|
|||
|
||||
let typed_ast = ast::typed::convert(ast)?;
|
||||
|
||||
let context = Context::create();
|
||||
let module =
|
||||
ast::llvm::convert(opts.path.display().to_string(), &context, typed_ast)?;
|
||||
if let Some(path) = opts.emit_ast {
|
||||
let mut file = File::create(&path)?;
|
||||
file.write(format!("{:#?}", typed_ast).as_bytes())?;
|
||||
}
|
||||
|
||||
{
|
||||
let file = File::create(&opts.out_path)?;
|
||||
module.write_bitcode_to_file(&file, true, true);
|
||||
println!("Emitted.");
|
||||
let mut codegen = LlvmIrCodegen::new(file);
|
||||
codegen.convert(typed_ast)?;
|
||||
}
|
||||
|
||||
// let ctx = ast::cranelift::convert(
|
||||
// opts.path.display().to_string(),
|
||||
// typed_ast,
|
||||
// )?;
|
||||
|
||||
// {
|
||||
// let file = File::create(&opts.out_path)?;
|
||||
// ctx.compile_and_emit();
|
||||
// println!("Emitted.");
|
||||
// }
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
61
src/utils.rs
61
src/utils.rs
|
@ -1,36 +1,35 @@
|
|||
// TODO: put layered environment here?
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
|
||||
use inkwell::{
|
||||
types::{BasicMetadataTypeEnum, BasicTypeEnum},
|
||||
values::{BasicMetadataValueEnum, BasicValueEnum},
|
||||
};
|
||||
|
||||
pub fn convert_type_to_metadata_type(
|
||||
a: BasicTypeEnum,
|
||||
) -> BasicMetadataTypeEnum {
|
||||
use BasicMetadataTypeEnum as B;
|
||||
use BasicTypeEnum as A;
|
||||
match a {
|
||||
A::IntType(a) => B::IntType(a),
|
||||
A::ArrayType(a) => B::ArrayType(a),
|
||||
A::FloatType(a) => B::FloatType(a),
|
||||
A::StructType(a) => B::StructType(a),
|
||||
A::VectorType(a) => B::VectorType(a),
|
||||
A::PointerType(a) => B::PointerType(a),
|
||||
}
|
||||
#[derive(Default)]
|
||||
pub struct LayeredEnv<K, V> {
|
||||
parent: Option<Box<LayeredEnv<K, V>>>,
|
||||
inner_map: HashMap<K, V>,
|
||||
}
|
||||
|
||||
pub fn convert_value_to_metadata_value(
|
||||
a: BasicValueEnum,
|
||||
) -> BasicMetadataValueEnum {
|
||||
use BasicMetadataValueEnum as B;
|
||||
use BasicValueEnum as A;
|
||||
match a {
|
||||
A::ArrayValue(a) => B::ArrayValue(a),
|
||||
A::IntValue(a) => B::IntValue(a),
|
||||
A::FloatValue(a) => B::FloatValue(a),
|
||||
A::PointerValue(a) => B::PointerValue(a),
|
||||
A::StructValue(a) => B::StructValue(a),
|
||||
A::VectorValue(a) => B::VectorValue(a),
|
||||
impl<K: Hash + Eq, V> LayeredEnv<K, V> {
|
||||
pub fn insert(&mut self, key: K, value: V) {
|
||||
self.inner_map.insert(key, value);
|
||||
}
|
||||
|
||||
pub fn push(self) -> LayeredEnv<K, V> {
|
||||
LayeredEnv {
|
||||
parent: Some(Box::new(self)),
|
||||
inner_map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop(self) -> LayeredEnv<K, V> {
|
||||
*self.parent.unwrap()
|
||||
}
|
||||
|
||||
pub fn lookup(&self, key: &K) -> Option<&V> {
|
||||
match self.inner_map.get(key) {
|
||||
Some(v) => Some(v),
|
||||
None => match self.parent.as_ref() {
|
||||
Some(p) => p.lookup(key),
|
||||
None => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue