correct naming resolution for called functions, including namespaces
This commit is contained in:
parent
c77a602545
commit
ddd7bd4472
6 changed files with 168 additions and 83 deletions
|
|
@ -2,4 +2,4 @@ fn get() -> string:
|
||||||
add("hello", "world")
|
add("hello", "world")
|
||||||
|
|
||||||
fn add(a: string, b: string) -> string:
|
fn add(a: string, b: string) -> string:
|
||||||
a + b
|
a + " " + b
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,27 @@ use crate::tokens::TokenType;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::vm::{
|
use crate::vm::{
|
||||||
OP_ADD, OP_AND, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_CHAR,
|
OP_ADD, OP_AND, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_CHAR,
|
||||||
OP_DEF_DATE, OP_DEF_F32, OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST,
|
OP_DEF_DATE, OP_DEF_F32, OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST, OP_DEF_MAP,
|
||||||
OP_DEF_MAP, OP_DEF_STRING, OP_DEF_STRUCT, OP_DEFINE, OP_DIVIDE, OP_EQUAL, OP_GET, OP_GREATER,
|
OP_DEF_STRING, OP_DEF_STRUCT, OP_DEFINE, OP_DIVIDE, OP_EQUAL, OP_GET, OP_GREATER,
|
||||||
OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_OR,
|
OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_OR, OP_PRINT,
|
||||||
OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT,
|
OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT,
|
||||||
};
|
};
|
||||||
|
use anyhow::anyhow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub fn compile(ast: &Vec<Statement>) -> anyhow::Result<Chunk> {
|
pub fn compile(
|
||||||
compile_name(ast, "/")
|
namespace: &str,
|
||||||
|
ast: &Vec<Statement>,
|
||||||
|
registry: &mut HashMap<String, Chunk>,
|
||||||
|
) -> anyhow::Result<Chunk> {
|
||||||
|
compile_name(ast, namespace, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compile_function(function: &Function) -> anyhow::Result<Chunk> {
|
pub(crate) fn compile_function(
|
||||||
|
function: &Function,
|
||||||
|
registry: &mut HashMap<String, Chunk>,
|
||||||
|
namespace: &str,
|
||||||
|
) -> anyhow::Result<Chunk> {
|
||||||
let mut compiler = Compiler::new(&function.name.lexeme);
|
let mut compiler = Compiler::new(&function.name.lexeme);
|
||||||
for parm in &function.parameters {
|
for parm in &function.parameters {
|
||||||
let name = parm.name.lexeme.clone();
|
let name = parm.name.lexeme.clone();
|
||||||
|
|
@ -24,12 +33,16 @@ pub(crate) fn compile_function(function: &Function) -> anyhow::Result<Chunk> {
|
||||||
compiler.emit_bytes(OP_DEFINE, name_index as u16);
|
compiler.emit_bytes(OP_DEFINE, name_index as u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(compiler.compile(&function.body)?)
|
Ok(compiler.compile(&function.body, registry, namespace)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compile_name(ast: &Vec<Statement>, name: &str) -> anyhow::Result<Chunk> {
|
pub(crate) fn compile_name(
|
||||||
let compiler = Compiler::new(name);
|
ast: &Vec<Statement>,
|
||||||
Ok(compiler.compile(ast)?)
|
namespace: &str,
|
||||||
|
registry: &mut HashMap<String, Chunk>,
|
||||||
|
) -> anyhow::Result<Chunk> {
|
||||||
|
let compiler = Compiler::new(namespace);
|
||||||
|
Ok(compiler.compile(ast, registry, namespace)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Compiler {
|
struct Compiler {
|
||||||
|
|
@ -37,7 +50,6 @@ struct Compiler {
|
||||||
had_error: bool,
|
had_error: bool,
|
||||||
current_line: usize,
|
current_line: usize,
|
||||||
vars: HashMap<String, usize>,
|
vars: HashMap<String, usize>,
|
||||||
functions: HashMap<String, usize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Compiler {
|
impl Compiler {
|
||||||
|
|
@ -47,20 +59,39 @@ impl Compiler {
|
||||||
had_error: false,
|
had_error: false,
|
||||||
current_line: 0,
|
current_line: 0,
|
||||||
vars: HashMap::new(),
|
vars: HashMap::new(),
|
||||||
functions: HashMap::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile(mut self, ast: &Vec<Statement>) -> anyhow::Result<Chunk> {
|
fn compile(
|
||||||
|
mut self,
|
||||||
|
ast: &Vec<Statement>,
|
||||||
|
registry: &mut HashMap<String, Chunk>,
|
||||||
|
namespace: &str,
|
||||||
|
) -> anyhow::Result<Chunk> {
|
||||||
for statement in ast {
|
for statement in ast {
|
||||||
self.compile_statement(statement)?
|
if let Statement::FunctionStmt { function } = statement {
|
||||||
|
self.emit_constant(Value::String(format!(
|
||||||
|
"{}.{}",
|
||||||
|
namespace,
|
||||||
|
function.name.lexeme.clone()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for statement in ast {
|
||||||
|
self.compile_statement(statement, registry, namespace)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.emit_byte(OP_RETURN);
|
self.emit_byte(OP_RETURN);
|
||||||
Ok(self.chunk)
|
Ok(self.chunk)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_statement(&mut self, statement: &Statement) -> anyhow::Result<()> {
|
fn compile_statement(
|
||||||
|
&mut self,
|
||||||
|
statement: &Statement,
|
||||||
|
registry: &mut HashMap<String, Chunk>,
|
||||||
|
namespace: &str,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
self.current_line = statement.line();
|
self.current_line = statement.line();
|
||||||
match statement {
|
match statement {
|
||||||
Statement::VarStmt {
|
Statement::VarStmt {
|
||||||
|
|
@ -70,39 +101,55 @@ impl Compiler {
|
||||||
} => {
|
} => {
|
||||||
let name_index = self.chunk.add_constant(Value::String(name.lexeme.clone()));
|
let name_index = self.chunk.add_constant(Value::String(name.lexeme.clone()));
|
||||||
self.vars.insert(name.lexeme.clone(), name_index);
|
self.vars.insert(name.lexeme.clone(), name_index);
|
||||||
self.compile_expression(initializer)?;
|
self.compile_expression(namespace, initializer, registry)?;
|
||||||
self.define_variable(var_type, name_index)?;
|
self.define_variable(var_type, name_index)?;
|
||||||
if let Expression::List {values, .. } = initializer {
|
if let Expression::List { values, .. } = initializer {
|
||||||
self.emit_byte(values.len() as u16);
|
self.emit_byte(values.len() as u16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Statement::PrintStmt { value } => {
|
Statement::PrintStmt { value } => {
|
||||||
self.compile_expression(value)?;
|
self.compile_expression(namespace, value, registry)?;
|
||||||
self.emit_byte(OP_PRINT);
|
self.emit_byte(OP_PRINT);
|
||||||
}
|
}
|
||||||
Statement::ExpressionStmt { expression } => {
|
Statement::ExpressionStmt { expression } => {
|
||||||
self.compile_expression(expression)?;
|
self.compile_expression(namespace, expression, registry)?;
|
||||||
}
|
}
|
||||||
Statement::FunctionStmt { function } => {
|
Statement::FunctionStmt { function } => {
|
||||||
let function_name = function.name.lexeme.clone();
|
let function_name = function.name.lexeme.clone();
|
||||||
let name_index = self.chunk.add_constant(Value::String(function_name.clone()));
|
self.emit_constant(Value::String(function_name.clone()));
|
||||||
self.functions.insert(function_name, name_index);
|
let compiled_function = compile_function(function, registry, namespace)?;
|
||||||
let compiled_function = compile_function(function)?;
|
registry.insert(
|
||||||
self.chunk.add_function(compiled_function);
|
format!("{}.{}", self.chunk.name, function_name),
|
||||||
|
compiled_function,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_expression(&mut self, expression: &Expression) -> anyhow::Result<()> {
|
fn compile_expression(
|
||||||
|
&mut self,
|
||||||
|
namespace: &str,
|
||||||
|
expression: &Expression,
|
||||||
|
registry: &mut HashMap<String, Chunk>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
match expression {
|
match expression {
|
||||||
Expression::FunctionCall {
|
Expression::FunctionCall {
|
||||||
name, arguments, ..
|
name, arguments, ..
|
||||||
} => {
|
} => {
|
||||||
println!("call {}",name);
|
let name = if let None = self.chunk.find_constant(&name) {
|
||||||
let name_index = *self.functions.get(name).unwrap();
|
format!("{}.{}", namespace, name)
|
||||||
|
} else {
|
||||||
|
name.clone()
|
||||||
|
};
|
||||||
|
println!("call {}", name);
|
||||||
|
let name_index = self
|
||||||
|
.chunk
|
||||||
|
.find_constant(&name)
|
||||||
|
.unwrap_or_else(|| self.emit_constant(name.into()) as usize);
|
||||||
|
|
||||||
for argument in arguments {
|
for argument in arguments {
|
||||||
self.compile_expression(argument)?;
|
self.compile_expression(namespace, argument, registry)?;
|
||||||
}
|
}
|
||||||
self.emit_bytes(OP_CALL, name_index as u16);
|
self.emit_bytes(OP_CALL, name_index as u16);
|
||||||
self.emit_byte(arguments.len() as u16);
|
self.emit_byte(arguments.len() as u16);
|
||||||
|
|
@ -111,18 +158,22 @@ impl Compiler {
|
||||||
let name_index = self.vars.get(name).unwrap();
|
let name_index = self.vars.get(name).unwrap();
|
||||||
self.emit_bytes(OP_GET, *name_index as u16);
|
self.emit_bytes(OP_GET, *name_index as u16);
|
||||||
}
|
}
|
||||||
Expression::Literal { value, .. } => self.emit_constant(value),
|
Expression::Literal { value, .. } => {
|
||||||
|
self.emit_constant(value.clone());
|
||||||
|
}
|
||||||
Expression::List { values, .. } => {
|
Expression::List { values, .. } => {
|
||||||
for expr in values {
|
for expr in values {
|
||||||
self.compile_expression(expr)?;
|
self.compile_expression(namespace, expr, registry)?;
|
||||||
}
|
}
|
||||||
// self.emit_bytes(OP_NEW_LIST, values.len() as u16);
|
// self.emit_bytes(OP_NEW_LIST, values.len() as u16);
|
||||||
}
|
}
|
||||||
Expression::Grouping { expression, .. } => self.compile_expression(expression)?,
|
Expression::Grouping { expression, .. } => {
|
||||||
|
self.compile_expression(namespace, expression, registry)?
|
||||||
|
}
|
||||||
Expression::Unary {
|
Expression::Unary {
|
||||||
operator, right, ..
|
operator, right, ..
|
||||||
} => {
|
} => {
|
||||||
self.compile_expression(right)?;
|
self.compile_expression(namespace, right, registry)?;
|
||||||
match operator.token_type {
|
match operator.token_type {
|
||||||
TokenType::Minus => {
|
TokenType::Minus => {
|
||||||
self.emit_byte(OP_NEGATE);
|
self.emit_byte(OP_NEGATE);
|
||||||
|
|
@ -139,8 +190,8 @@ impl Compiler {
|
||||||
right,
|
right,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
self.compile_expression(left)?;
|
self.compile_expression(namespace, left, registry)?;
|
||||||
self.compile_expression(right)?;
|
self.compile_expression(namespace, right, registry)?;
|
||||||
match operator.token_type {
|
match operator.token_type {
|
||||||
TokenType::Plus => self.emit_byte(OP_ADD),
|
TokenType::Plus => self.emit_byte(OP_ADD),
|
||||||
TokenType::Minus => self.emit_byte(OP_SUBTRACT),
|
TokenType::Minus => self.emit_byte(OP_SUBTRACT),
|
||||||
|
|
@ -196,8 +247,9 @@ impl Compiler {
|
||||||
self.emit_byte(b2);
|
self.emit_byte(b2);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_constant(&mut self, value: &Value) {
|
fn emit_constant(&mut self, value: Value) -> u16 {
|
||||||
let index = self.chunk.add_constant(value.clone());
|
let index = self.chunk.add_constant(value) as u16;
|
||||||
self.emit_bytes(OP_CONSTANT, index as u16);
|
self.emit_bytes(OP_CONSTANT, index);
|
||||||
|
index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
37
src/chunk.rs
37
src/chunk.rs
|
|
@ -1,20 +1,30 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::vm::{
|
use crate::vm::{
|
||||||
OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_F32,
|
OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CALL, OP_CONSTANT, OP_DEF_BOOL, OP_DEF_F32,
|
||||||
OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST, OP_DEF_STRING, OP_DEFINE, OP_DIVIDE, OP_EQUAL,
|
OP_DEF_F64, OP_DEF_I32, OP_DEF_I64, OP_DEF_LIST, OP_DEF_STRING, OP_DEFINE, OP_DIVIDE, OP_EQUAL,
|
||||||
OP_GET, OP_GREATER, OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_MULTIPLY, OP_NEGATE,
|
OP_GET, OP_GREATER, OP_GREATER_EQUAL, OP_LESS, OP_LESS_EQUAL, OP_MULTIPLY, OP_NEGATE, OP_NOT,
|
||||||
OP_NOT, OP_POP, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT,
|
OP_POP, OP_PRINT, OP_RETURN, OP_SHL, OP_SHR, OP_SUBTRACT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Chunk {
|
pub struct Chunk {
|
||||||
name: String,
|
pub(crate) name: String,
|
||||||
pub code: Vec<u16>,
|
pub code: Vec<u16>,
|
||||||
pub constants: Vec<Value>,
|
pub constants: Vec<Value>,
|
||||||
lines: Vec<usize>,
|
lines: Vec<usize>,
|
||||||
pub functions: HashMap<String, Chunk>,
|
}
|
||||||
// pub(crate) functions_by_index: Vec<Chunk>,
|
|
||||||
|
impl Chunk {
|
||||||
|
pub(crate) fn find_constant(&self, p0: &String) -> Option<usize> {
|
||||||
|
for (i, constant) in self.constants.iter().enumerate() {
|
||||||
|
if let Value::String(s) = constant {
|
||||||
|
if s == p0 {
|
||||||
|
return Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chunk {
|
impl Chunk {
|
||||||
|
|
@ -24,8 +34,6 @@ impl Chunk {
|
||||||
code: Vec::new(),
|
code: Vec::new(),
|
||||||
constants: vec![],
|
constants: vec![],
|
||||||
lines: vec![],
|
lines: vec![],
|
||||||
functions: HashMap::new(),
|
|
||||||
// functions_by_index: Vec::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,15 +47,7 @@ impl Chunk {
|
||||||
self.constants.len() - 1
|
self.constants.len() - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_function(&mut self, function: Chunk) {
|
|
||||||
// self.functions_by_index.push(function.clone());
|
|
||||||
self.functions.insert(function.name.to_string(), function);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn disassemble(&self) {
|
pub fn disassemble(&self) {
|
||||||
for f in self.functions.values() {
|
|
||||||
f.disassemble();
|
|
||||||
}
|
|
||||||
println!("== {} ==", self.name);
|
println!("== {} ==", self.name);
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
while offset < self.code.len() {
|
while offset < self.code.len() {
|
||||||
|
|
@ -110,7 +110,10 @@ impl Chunk {
|
||||||
fn call_inst(&self, op: &str, offset: usize) -> usize {
|
fn call_inst(&self, op: &str, offset: usize) -> usize {
|
||||||
let constant = self.code[offset + 1];
|
let constant = self.code[offset + 1];
|
||||||
let num_args = self.code[offset + 2];
|
let num_args = self.code[offset + 2];
|
||||||
println!("{} {}:{}({}):", op, constant, &self.constants[constant as usize], num_args);
|
println!(
|
||||||
|
"{} {}:{}({}):",
|
||||||
|
op, constant, &self.constants[constant as usize], num_args
|
||||||
|
);
|
||||||
offset + 3
|
offset + 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
42
src/main.rs
42
src/main.rs
|
|
@ -9,6 +9,7 @@ use crudlang::scanner::scan;
|
||||||
use crudlang::vm::interpret;
|
use crudlang::vm::interpret;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::hash::Hash;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
|
@ -17,6 +18,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
let mut paths = HashMap::new();
|
let mut paths = HashMap::new();
|
||||||
|
let mut registry = HashMap::new();
|
||||||
for entry in WalkDir::new("source").into_iter().filter_map(|e| e.ok()) {
|
for entry in WalkDir::new("source").into_iter().filter_map(|e| e.ok()) {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if path.is_file() && path.ends_with("web.crud") {
|
if path.is_file() && path.ends_with("web.crud") {
|
||||||
|
|
@ -25,10 +27,13 @@ async fn main() -> anyhow::Result<()> {
|
||||||
let tokens = scan(&source);
|
let tokens = scan(&source);
|
||||||
match ast_compiler::compile(tokens) {
|
match ast_compiler::compile(tokens) {
|
||||||
Ok(statements) => {
|
Ok(statements) => {
|
||||||
let chunk = compile(&statements)?;
|
let path = path
|
||||||
let path = path.strip_prefix("source")?.to_str().unwrap();
|
.strip_prefix("source")?
|
||||||
let path = path.replace("/web.crud", "");
|
.to_str()
|
||||||
paths.insert(format!("/{}", path), chunk);
|
.unwrap()
|
||||||
|
.replace(".crud", "");
|
||||||
|
let chunk = compile(&path, &statements, &mut registry)?;
|
||||||
|
paths.insert(path, chunk);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{}", e);
|
println!("{}", e);
|
||||||
|
|
@ -38,16 +43,18 @@ async fn main() -> anyhow::Result<()> {
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let registry = Arc::new(registry);
|
||||||
if !paths.is_empty() {
|
if !paths.is_empty() {
|
||||||
let mut app = Router::new();
|
let mut app = Router::new();
|
||||||
for (path, code) in paths.iter() {
|
for (path, code) in paths.iter() {
|
||||||
let code = code.functions.get("get").unwrap();
|
let state = Arc::new(AppState {
|
||||||
let state = Arc::new(AppState { code: code.clone() });
|
name: format!("{}.get", path),
|
||||||
|
registry: registry.clone(),
|
||||||
|
});
|
||||||
println!("adding {}", path);
|
println!("adding {}", path);
|
||||||
app = app.route(path, get(handle_get).with_state(state.clone()));
|
app = app.route(&format!("/{}",path.replace("/web", "")), get(handle_get).with_state(state.clone()));
|
||||||
// .with_state(state);
|
|
||||||
}
|
}
|
||||||
// run our app with hyper, listening globally on port 3000
|
|
||||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
|
||||||
println!("listening on {}", listener.local_addr()?);
|
println!("listening on {}", listener.local_addr()?);
|
||||||
axum::serve(listener, app).await?;
|
axum::serve(listener, app).await?;
|
||||||
|
|
@ -57,11 +64,17 @@ async fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct AppState {
|
struct AppState {
|
||||||
code: Chunk,
|
name: String,
|
||||||
|
registry: Arc<HashMap<String, Chunk>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_get(State(state): State<Arc<AppState>>) -> Result<Json<String>, StatusCode> {
|
async fn handle_get(State(state): State<Arc<AppState>>) -> Result<Json<String>, StatusCode> {
|
||||||
Ok(Json(interpret(&state.code).await.unwrap().to_string()))
|
Ok(Json(
|
||||||
|
interpret(&state.registry, &state.name)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.to_string(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -78,18 +91,19 @@ fn hello(name: string) -> string:
|
||||||
"Hello "+name
|
"Hello "+name
|
||||||
hello("sander")"#,
|
hello("sander")"#,
|
||||||
);
|
);
|
||||||
|
let mut registry = HashMap::new();
|
||||||
match ast_compiler::compile(tokens) {
|
match ast_compiler::compile(tokens) {
|
||||||
Ok(statements) => {
|
Ok(statements) => {
|
||||||
println!("{:?}", statements);
|
println!("{:?}", statements);
|
||||||
let chunk = compile(&statements)?;
|
let chunk = compile("", &statements, &mut registry)?;
|
||||||
chunk.disassemble();
|
chunk.disassemble();
|
||||||
println!("{}", interpret(&chunk).await?);
|
// println!("{}", interpret(&chunk).await?);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{}", e)
|
println!("{}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println!("{:?}", registry);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
src/value.rs
17
src/value.rs
|
|
@ -96,6 +96,19 @@ impl Into<Value> for &str {
|
||||||
Value::String(self.to_string())
|
Value::String(self.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<String> for Value {
|
||||||
|
fn from(s: String) -> Self {
|
||||||
|
Value::String(s.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&String> for Value {
|
||||||
|
fn from(s: &String) -> Self {
|
||||||
|
Value::String(s.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Into<Value> for char {
|
impl Into<Value> for char {
|
||||||
fn into(self) -> Value {
|
fn into(self) -> Value {
|
||||||
Value::Char(self)
|
Value::Char(self)
|
||||||
|
|
@ -171,8 +184,8 @@ impl Add<&Value> for &Value {
|
||||||
(Value::U64(a), Value::U64(b)) => Ok(Value::U64(a + b)),
|
(Value::U64(a), Value::U64(b)) => Ok(Value::U64(a + b)),
|
||||||
(Value::F32(a), Value::F32(b)) => Ok(Value::F32(a + b)),
|
(Value::F32(a), Value::F32(b)) => Ok(Value::F32(a + b)),
|
||||||
(Value::F64(a), Value::F64(b)) => Ok(Value::F64(a + b)),
|
(Value::F64(a), Value::F64(b)) => Ok(Value::F64(a + b)),
|
||||||
(Value::String(s), Value::I32(i)) => Ok(Value::String(format!("{}{}", s, i))),
|
(Value::String(s), Value::I32(i)) => Ok(format!("{}{}", s, i).into()),
|
||||||
(Value::String(s), Value::I64(i)) => Ok(Value::String(format!("{}{}", s, i))),
|
(Value::String(s), Value::I64(i)) => Ok(format!("{}{}", s, i).into()),
|
||||||
(Value::String(s), Value::U32(u)) => Ok(Value::String(format!("{}{}", s, u))),
|
(Value::String(s), Value::U32(u)) => Ok(Value::String(format!("{}{}", s, u))),
|
||||||
(Value::String(s), Value::U64(u)) => Ok(Value::String(format!("{}{}", s, u))),
|
(Value::String(s), Value::U64(u)) => Ok(Value::String(format!("{}{}", s, u))),
|
||||||
(Value::String(s), Value::F32(f)) => Ok(Value::String(format!("{}{}", s, f))),
|
(Value::String(s), Value::F32(f)) => Ok(Value::String(format!("{}{}", s, f))),
|
||||||
|
|
|
||||||
27
src/vm.rs
27
src/vm.rs
|
|
@ -20,23 +20,24 @@ macro_rules! define_var {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Vm {
|
pub struct Vm<'a> {
|
||||||
ip: usize,
|
ip: usize,
|
||||||
stack: Vec<Value>,
|
stack: Vec<Value>,
|
||||||
local_vars: HashMap<String, Value>,
|
local_vars: HashMap<String, Value>,
|
||||||
error_occurred: bool,
|
error_occurred: bool,
|
||||||
arena: Bump,
|
registry: &'a HashMap<String, Chunk>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn interpret(chunk: &Chunk) -> anyhow::Result<Value> {
|
pub async fn interpret(registry: &HashMap<String, Chunk>, function: &str) -> anyhow::Result<Value> {
|
||||||
|
let chunk = registry.get(function).unwrap().clone();
|
||||||
let mut vm = Vm {
|
let mut vm = Vm {
|
||||||
ip: 0,
|
ip: 0,
|
||||||
stack: vec![],
|
stack: vec![],
|
||||||
local_vars: HashMap::new(),
|
local_vars: HashMap::new(),
|
||||||
error_occurred: false,
|
error_occurred: false,
|
||||||
arena: Bump::new(),
|
registry,
|
||||||
};
|
};
|
||||||
vm.run(chunk, vec![])
|
vm.run(&chunk, vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interpret_function(chunk: &Chunk, args: Vec<Value>) -> anyhow::Result<Value> {
|
pub fn interpret_function(chunk: &Chunk, args: Vec<Value>) -> anyhow::Result<Value> {
|
||||||
|
|
@ -45,12 +46,12 @@ pub fn interpret_function(chunk: &Chunk, args: Vec<Value>) -> anyhow::Result<Val
|
||||||
stack: vec![],
|
stack: vec![],
|
||||||
local_vars: HashMap::new(),
|
local_vars: HashMap::new(),
|
||||||
error_occurred: false,
|
error_occurred: false,
|
||||||
arena: Bump::new(),
|
registry: &HashMap::new(),
|
||||||
};
|
};
|
||||||
vm.run(chunk, args)
|
vm.run(chunk, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vm {
|
impl <'a> Vm<'a> {
|
||||||
fn run(&mut self, chunk: &Chunk, args: Vec<Value>) -> anyhow::Result<Value> {
|
fn run(&mut self, chunk: &Chunk, args: Vec<Value>) -> anyhow::Result<Value> {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
self.push(arg);
|
self.push(arg);
|
||||||
|
|
@ -145,16 +146,18 @@ impl Vm {
|
||||||
}
|
}
|
||||||
OP_CALL => {
|
OP_CALL => {
|
||||||
let function_name_index = self.read(chunk);
|
let function_name_index = self.read(chunk);
|
||||||
let function_name = chunk.constants[function_name_index].to_string();
|
|
||||||
let function = chunk.functions.get(&function_name).unwrap();
|
|
||||||
let mut args = vec![];
|
|
||||||
let num_args = self.read(chunk);
|
let num_args = self.read(chunk);
|
||||||
|
|
||||||
|
let mut args = vec![];
|
||||||
for _ in 0..num_args {
|
for _ in 0..num_args {
|
||||||
let arg = self.pop();
|
let arg = self.pop();
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
}
|
}
|
||||||
args.reverse();
|
// args.reverse();
|
||||||
let result = interpret_function(function, args)?;
|
|
||||||
|
let function_name = chunk.constants[function_name_index].to_string();
|
||||||
|
let function_chunk = self.registry.get(&function_name).unwrap();
|
||||||
|
let result = interpret_function(function_chunk, args)?;
|
||||||
self.push(result);
|
self.push(result);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue