Skip to content

Commit ccafc3c

Browse files
committed
Embed common and core source code in the binaries, such that the binary can be run from anywhere.
1 parent 08adb0c commit ccafc3c

File tree

10 files changed

+74
-33
lines changed

10 files changed

+74
-33
lines changed

src/cli/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn run(args: &ArgMatches) -> RResult<ExitCode> {
2525
let start = dump_start(format!("check for {} file(s)", paths.len()).as_str());
2626

2727
let mut runtime = Runtime::new()?;
28-
runtime.repository.add("common", PathBuf::from("monoteny"));
28+
runtime.add_common_repository();
2929

3030
let mut error_count = 0;
3131
for path in paths {

src/cli/run.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub fn run(args: &ArgMatches) -> RResult<ExitCode> {
1919
let input_path = args.get_one::<PathBuf>("PATH").unwrap();
2020

2121
let mut runtime = Runtime::new()?;
22-
runtime.repository.add("common", PathBuf::from("monoteny"));
22+
runtime.add_common_repository();
2323

2424
let module = runtime.load_file_as_module(input_path, module_name("main"))?;
2525

src/cli/transpile.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use itertools::Itertools;
88
use crate::error::RResult;
99
use crate::interpreter::runtime::Runtime;
1010
use crate::program::module::{Module, module_name};
11-
use crate::{interpreter, transpiler};
11+
use crate::{interpreter, repository, transpiler};
1212
use crate::cli::logging::{dump_failure, dump_start, dump_success};
1313
use crate::transpiler::LanguageContext;
1414
use crate::util::file_writer::write_file_safe;
@@ -50,7 +50,7 @@ pub fn run(args: &ArgMatches) -> RResult<ExitCode> {
5050
};
5151

5252
let mut runtime = Runtime::new()?;
53-
runtime.repository.add("common", PathBuf::from("monoteny"));
53+
runtime.add_common_repository();
5454

5555
let module = runtime.load_file_as_module(input_path, module_name("main"))?;
5656

src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub type RResult<V> = Result<V, Vec<RuntimeError>>;
1919
impl RuntimeError {
2020
pub fn print(&self) {
2121
match &self.path {
22-
None => self.print_snippet(Snippet::source(&self.title)),
22+
None => println!("{}", self.title),
2323
Some(path) => match fs::read_to_string(path) {
2424
Ok(source) => self.print_snippet(
2525
Snippet::source(source.as_str())

src/interpreter/builtins.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod primitives;
22
pub mod traits;
33
pub mod vm;
4+
pub mod modules;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use std::collections::HashMap;
2+
use crate::repository;
3+
4+
pub fn create_core_loader() -> repository::Loader {
5+
repository::Loader::Intrinsic(
6+
HashMap::from([
7+
(vec!["core".to_string()], include_str!("../../../monoteny/core.monoteny")),
8+
(vec!["core".to_string(), "bool".to_string()], include_str!("../../../monoteny/core/bool.monoteny")),
9+
(vec!["core".to_string(), "debug".to_string()], include_str!("../../../monoteny/core/debug.monoteny")),
10+
(vec!["core".to_string(), "run".to_string()], include_str!("../../../monoteny/core/run.monoteny")),
11+
(vec!["core".to_string(), "strings".to_string()], include_str!("../../../monoteny/core/strings.monoteny")),
12+
(vec!["core".to_string(), "transpilation".to_string()], include_str!("../../../monoteny/core/transpilation.monoteny")),
13+
]),
14+
)
15+
}
16+
17+
pub fn create_common_loader() -> repository::Loader {
18+
repository::Loader::Intrinsic(
19+
HashMap::from([
20+
(vec!["common".to_string()], include_str!("../../../monoteny/common.monoteny")),
21+
(vec!["common".to_string(), "debug".to_string()], include_str!("../../../monoteny/common/debug.monoteny")),
22+
(vec!["common".to_string(), "math".to_string()], include_str!("../../../monoteny/common/math.monoteny")),
23+
(vec!["common".to_string(), "precedence".to_string()], include_str!("../../../monoteny/common/precedence.monoteny")),
24+
]),
25+
)
26+
}

src/interpreter/runtime.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use std::rc::Rc;
44

55
use itertools::Itertools;
66

7-
use crate::{ast, parser, program, resolver};
8-
use crate::cli::run::run;
7+
use crate::{ast, parser, program, repository, resolver};
98
use crate::error::{RResult, RuntimeError};
109
use crate::interpreter::builtins;
1110
use crate::interpreter::compile::compile_server::CompileServer;
@@ -65,7 +64,7 @@ impl Runtime {
6564
runtime.base_scope = Rc::new(runtime.make_scope()?);
6665

6766
// Load core
68-
runtime.repository.add("core", PathBuf::from("monoteny"));
67+
runtime.repository.add("core", builtins::modules::create_core_loader());
6968
runtime.get_or_load_module(&module_name("core"))?;
7069

7170
// Final scope can be loaded.
@@ -77,6 +76,10 @@ impl Runtime {
7776
Ok(runtime)
7877
}
7978

79+
pub fn add_common_repository(&mut self) {
80+
self.repository.add("common", builtins::modules::create_common_loader());
81+
}
82+
8083
fn make_scope(&mut self) -> RResult<scopes::Scope<'static>> {
8184
let mut scope = scopes::Scope::new();
8285

@@ -101,8 +104,28 @@ impl Runtime {
101104
}
102105

103106
// Gotta load the module first.
104-
let path = self.repository.resolve_module_path(name)?;
105-
let module = self.load_file_as_module(&path, name.clone())?;
107+
let Some(first_part) = name.first() else {
108+
return Err(RuntimeError::error("Module name is empty...").to_array());
109+
};
110+
111+
let Some(loader) = self.repository.entries.get(first_part) else {
112+
return Err(RuntimeError::error(format!("Module not in repository: {}", first_part).as_str()).to_array());
113+
};
114+
115+
let module = match loader {
116+
repository::Loader::Path(base_path) => {
117+
let path = base_path.join(PathBuf::from(format!("{}.monoteny", name.join("/").as_str())));
118+
self.load_file_as_module(&path, name.clone())?
119+
},
120+
repository::Loader::Intrinsic(map) => {
121+
let text = map.get(name)
122+
.map(ToString::to_string) // TODO Expensive copy from string literal :/
123+
.ok_or(RuntimeError::error(format!("Error loading {:?}: missing intrinsic", name).as_str()).to_array())?;
124+
self.load_text_as_module(&text, name.clone())?
125+
// TODO Should map error as 'in string xx', like in load_file_as_module
126+
}
127+
};
128+
106129
self.source.module_by_name.insert(name.clone(), module);
107130
Ok(&self.source.module_by_name[name])
108131
}

src/interpreter/tests.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ mod tests {
2323
#[test]
2424
fn run_expression() -> RResult<()> {
2525
let mut runtime = Runtime::new()?;
26-
runtime.repository.add("common", PathBuf::from("monoteny"));
26+
runtime.add_common_repository();
2727

2828
let mut chunk = Chunk::new();
2929
chunk.push_with_u16(OpCode::LOAD16, 2);
@@ -47,7 +47,7 @@ mod tests {
4747

4848
fn test_runs(path: &str) -> RResult<String> {
4949
let mut runtime = Runtime::new()?;
50-
runtime.repository.add("common", PathBuf::from("monoteny"));
50+
runtime.add_common_repository();
5151

5252
let module = runtime.load_file_as_module(&PathBuf::from(path), module_name("main"))?;
5353

@@ -151,7 +151,7 @@ mod tests {
151151
#[test]
152152
fn assertions() -> RResult<()> {
153153
let mut runtime = Runtime::new()?;
154-
runtime.repository.add("common", PathBuf::from("monoteny"));
154+
runtime.add_common_repository();
155155

156156
let module = runtime.load_file_as_module(&PathBuf::from("test-code/debug/assert.monoteny"), module_name("main"))?;
157157

@@ -181,7 +181,7 @@ mod tests {
181181
#[test]
182182
fn anonymous_type() -> RResult<()> {
183183
let mut runtime = Runtime::new()?;
184-
runtime.repository.add("common", PathBuf::from("monoteny"));
184+
runtime.add_common_repository();
185185

186186
let (expression, _) = parse_expression("String")?;
187187
let result = runtime.evaluate_anonymous_expression(

src/repository.rs

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
use std::collections::HashMap;
22
use std::path::PathBuf;
3-
use crate::error::{RResult, RuntimeError};
4-
53
use crate::program::module::ModuleName;
64

5+
pub enum Loader {
6+
Path(PathBuf),
7+
Intrinsic(HashMap<ModuleName, &'static str>)
8+
}
9+
710
pub struct Repository {
8-
pub entries: HashMap<String, PathBuf>,
11+
pub entries: HashMap<String, Loader>,
912
}
1013

1114
impl Repository {
@@ -15,19 +18,7 @@ impl Repository {
1518
})
1619
}
1720

18-
pub fn add(&mut self, name: &str, path: PathBuf) {
19-
self.entries.insert(name.to_string(), path);
20-
}
21-
22-
pub fn resolve_module_path(&self, name: &ModuleName) -> RResult<PathBuf> {
23-
let Some(first_part) = name.first() else {
24-
return Err(RuntimeError::error("Module name is empty...").to_array());
25-
};
26-
27-
let Some(base_path) = self.entries.get(first_part) else {
28-
return Err(RuntimeError::error(format!("Module not in repository: {}", first_part).as_str()).to_array());
29-
};
30-
31-
Ok(base_path.join(PathBuf::from(format!("{}.monoteny", name.join("/").as_str()))))
21+
pub fn add(&mut self, name: &str, loader: Loader) {
22+
self.entries.insert(name.to_string(), loader);
3223
}
3324
}

src/transpiler/tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ mod tests {
1313

1414
fn test_transpiles(path: &str) -> RResult<String> {
1515
let mut runtime = Runtime::new()?;
16-
runtime.repository.add("common", PathBuf::from("monoteny"));
16+
runtime.add_common_repository();
1717

1818
let module = runtime.load_file_as_module(&PathBuf::from(path), module_name("main"))?;
1919
let context = transpiler::python::Context::new(&runtime);
@@ -30,7 +30,7 @@ mod tests {
3030
#[test]
3131
fn uninterpreted_hello_world() -> RResult<()> {
3232
let mut runtime = Runtime::new()?;
33-
runtime.repository.add("common", PathBuf::from("monoteny"));
33+
runtime.add_common_repository();
3434

3535
let module = runtime.load_file_as_module(&PathBuf::from("test-code/hello_world.monoteny"), module_name("main"))?;
3636
let main_function = module.main_functions.iter().at_most_one().unwrap().unwrap();

0 commit comments

Comments
 (0)