Skip to content

Commit

Permalink
Added fully qualified names
Browse files Browse the repository at this point in the history
  • Loading branch information
ecton committed Mar 1, 2024
1 parent 1c415e0 commit 8f3efc5
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 42 deletions.
9 changes: 8 additions & 1 deletion src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ impl<'a> Scope<'a> {
fn compile_expression(&mut self, expr: &Ranged<Expression>, dest: OpDestination) {
self.compiler.code.set_current_source_range(expr.range());
match &**expr {
Expression::RootModule => {
self.compiler
.code
.resolve(Symbol::sigil_symbol().clone(), dest);
}
Expression::Literal(literal) => self.compile_literal(literal, dest),
Expression::Lookup(lookup) => {
if let Some(base) = &lookup.base {
Expand Down Expand Up @@ -1371,7 +1376,8 @@ impl<'a> Scope<'a> {
| Expression::Binary(_)
| Expression::Module(_)
| Expression::Function(_)
| Expression::Variable(_) => Err(expr.1),
| Expression::Variable(_)
| Expression::RootModule => Err(expr.1),
}
}

Expand Down Expand Up @@ -1617,6 +1623,7 @@ impl<'a> Scope<'a> {
| Expression::Loop(_)
| Expression::Break(_)
| Expression::Continue(_)
| Expression::RootModule
| Expression::Return(_) => {
ValueOrSource::Stack(self.compile_expression_into_temporary(source))
}
Expand Down
1 change: 1 addition & 0 deletions src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ static_symbols!(
pub_symbol => "pub",
return_symbol => "return",
set_symbol => "set",
sigil_symbol => "$",
super_symbol => "super",
then_symbol => "then",
throw_symbol => "throw",
Expand Down
9 changes: 9 additions & 0 deletions src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ impl From<(SourceId, RangeInclusive<usize>)> for SourceRange {

#[derive(Debug, Clone, PartialEq)]
pub enum Expression {
RootModule,
Literal(Literal),
Lookup(Box<Lookup>),
If(Box<IfExpression>),
Expand Down Expand Up @@ -971,6 +972,7 @@ impl Parselet for Term {
| Token::Regex(_)
| Token::String(_)
| Token::Symbol(_)
| Token::Sigil(_)
)
}
}
Expand Down Expand Up @@ -1011,6 +1013,13 @@ impl PrefixParselet for Term {
token.1,
Expression::Literal(Literal::Symbol(sym)),
)),
Token::Sigil(sym) => {
if &sym == Symbol::sigil_symbol() {
Ok(Ranged::new(token.1, Expression::RootModule))
} else {
todo!("macro!!!!!")
}
}
_ => unreachable!("parse called with invalid token"),
}
}
Expand Down
53 changes: 38 additions & 15 deletions src/syntax/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub enum Token {
Comment,
Identifier(Symbol),
Symbol(Symbol),
Sigil(Symbol),
Label(Symbol),
Int(i64),
UInt(u64),
Expand Down Expand Up @@ -75,7 +76,9 @@ impl Hash for Token {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
core::mem::discriminant(self).hash(state);
match self {
Token::Identifier(t) | Token::Label(t) | Token::Symbol(t) => t.hash(state),
Token::Identifier(t) | Token::Label(t) | Token::Symbol(t) | Token::Sigil(t) => {
t.hash(state);
}
Token::Int(t) => t.hash(state),
Token::UInt(t) => t.hash(state),
Token::Float(t) => t.to_bits().hash(state),
Expand Down Expand Up @@ -206,6 +209,7 @@ impl Iterator for Tokens<'_> {
}

(start, '"') => self.tokenize_string(start),
(start, '$') => Ok(self.tokenize_sigil(start)),
(start, '@') if self.chars.peek().map_or(false, unicode_ident::is_xid_start) => {
let ch = self.chars.next().expect("just peekend").1;
Ok(self.tokenize_label(start, ch))
Expand All @@ -229,20 +233,7 @@ impl Iterator for Tokens<'_> {
(start, '.') if self.chars.peek().map_or(false, |ch| ch.is_ascii_digit()) => {
self.tokenize_number(start, '.')
}
(start, '.') if self.chars.peek() == Some('.') => {
self.chars.next();
match self.chars.peek() {
Some('=') => {
self.chars.next();
Ok(self.chars.ranged(start.., Token::RangeInclusive))
}
Some('.') => {
self.chars.next();
Ok(self.chars.ranged(start.., Token::Ellipses))
}
_ => Ok(self.chars.ranged(start.., Token::Range)),
}
}
(start, '.') if self.chars.peek() == Some('.') => Ok(self.tokenize_range(start)),
(start, '*') if self.chars.peek() == Some('*') => {
self.chars.next();
Ok(self.chars.ranged(start.., Token::Power))
Expand Down Expand Up @@ -320,6 +311,38 @@ impl<'a> Tokens<'a> {
self
}

fn tokenize_sigil(&mut self, start: usize) -> Ranged<Token> {
let symbol = if let Some(ch) = self
.chars
.peek()
.filter(|ch| unicode_ident::is_xid_start(*ch))
{
self.chars.next();
self.tokenize_identifier_symbol(start, ch)
} else {
self.chars.ranged(start.., Symbol::sigil_symbol().clone())
};

symbol.map(Token::Sigil)
}

fn tokenize_range(&mut self, start: usize) -> Ranged<Token> {
let second_dot = self.chars.next();
debug_assert!(matches!(second_dot, Some((_, '.'))));

match self.chars.peek() {
Some('=') => {
self.chars.next();
self.chars.ranged(start.., Token::RangeInclusive)
}
Some('.') => {
self.chars.next();
self.chars.ranged(start.., Token::Ellipses)
}
_ => self.chars.ranged(start.., Token::Range),
}
}

fn tokenize_number(
&mut self,
start: usize,
Expand Down
55 changes: 30 additions & 25 deletions src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,34 +435,39 @@ impl Vm {
}

pub fn resolve(&mut self, name: &Symbol) -> Result<Value, Fault> {
if let Some(path) = name.strip_prefix("$.") {
if let Some(path) = name.strip_prefix('$') {
let mut module = self.modules[0].clone();
let mut path = path.split('.').peekable();
let name = loop {
let Some(name) = path.next() else {
return Err(Fault::UnknownSymbol);
};
let name = Symbol::from(name);
if path.peek().is_some() {
let declarations = module.declarations();
let value = &declarations.get(&name).ok_or(Fault::UnknownSymbol)?.value;
let Some(inner) = value.as_dynamic::<Module>() else {
return Err(Fault::MissingModule);
path.next();
return if path.peek().is_none() {
Ok(module.to_value())
} else {
let name = loop {
let Some(name) = path.next() else {
return Err(Fault::UnknownSymbol);
};
drop(declarations);
module = inner;
} else {
// Final path component
break name;
}
};
let name = Symbol::from(name);
if path.peek().is_some() {
let declarations = module.declarations();
let value = &declarations.get(&name).ok_or(Fault::UnknownSymbol)?.value;
let Some(inner) = value.as_dynamic::<Module>() else {
return Err(Fault::MissingModule);
};
drop(declarations);
module = inner;
} else {
// Final path component
break name;
}
};

return Ok(module
.declarations()
.get(&name)
.ok_or(Fault::UnknownSymbol)?
.value
.clone());
Ok(module
.declarations()
.get(&name)
.ok_or(Fault::UnknownSymbol)?
.value
.clone())
};
}

let current_frame = &self.frames[self.current_frame];
Expand Down Expand Up @@ -712,7 +717,7 @@ impl Vm {
Ordering::Equal => return Ok(StepResult::Complete),
Ordering::Greater => return Err(Fault::InvalidInstructionAddress),
};
// println!("Executing {instruction:?}");
println!("Executing {instruction:?}");
let next_instruction = StepResult::from(address.checked_add(1));
let result = match instruction {
LoadedOp::Return => return Ok(StepResult::Complete),
Expand Down
13 changes: 13 additions & 0 deletions tests/cases/mod.rsn
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,17 @@ child_mod_private: {
foo.bar.a
"#,
output: Fault(Exception(Exception { value: Symbol("undefined"), backtrace: [SourceRange { source_id: SourceId(None), start: 106, length: 7 }] })),
}

sigil_root: {
src: r#"
mod foo {
pub mod bar {
pub fn baz() => $.value;
}
};
pub let value = 42;
foo.bar.baz()
"#,
output: Int(42),
}
2 changes: 1 addition & 1 deletion tests/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use serde::Deserialize;

fn main() {
let filter = std::env::args().nth(1).unwrap_or_default();
// let filter = String::from("tuple_remaining");
// let filter = String::from("sigil_root");
for entry in std::fs::read_dir("tests/cases").unwrap() {
let entry = entry.unwrap().path();
if entry.extension().map_or(false, |ext| ext == "rsn") {
Expand Down

0 comments on commit 8f3efc5

Please sign in to comment.