Skip to content

Commit

Permalink
Merge pull request #140 from kyleect/add-package-path-to-files
Browse files Browse the repository at this point in the history
Add initial implementation of declaring package paths in locks file
  • Loading branch information
kyleect authored Jan 5, 2024
2 parents 40c1d61 + a8ea82a commit 45ba9bc
Show file tree
Hide file tree
Showing 20 changed files with 145 additions and 33 deletions.
1 change: 1 addition & 0 deletions res/examples/package/double_path_seperator.locks
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package path::::to; // out: SyntaxError: unexpected "::"
1 change: 1 addition & 0 deletions res/examples/package/end_with_path_separator.locks
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package path::; // out: SyntaxError: unexpected ";"
1 change: 1 addition & 0 deletions res/examples/package/multiple_paths.locks
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package multiple::paths;
1 change: 1 addition & 0 deletions res/examples/package/no_path.locks
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package; // out: SyntaxError: unexpected ";"
5 changes: 5 additions & 0 deletions res/examples/package/package_path_and_statements.locks
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package test;

fn sum (a, b) => a + b;

println(sum(1, 10)); // out: 11
1 change: 1 addition & 0 deletions res/examples/package/single_path.locks
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package single_path;
1 change: 1 addition & 0 deletions res/examples/package/start_with_path_separator.locks
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package ::path; // out: SyntaxError: unexpected "::"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package::path; // out: SyntaxError: unexpected "::"
30 changes: 23 additions & 7 deletions res/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ grammar<'err>(
errors: &'err mut Vec<ParseError<usize, lexer::Token, ErrorS>>
);

pub Program: ast::Program = <stmts:Spanned<Decl>*> => ast::Program { <> };
pub Program: ast::Program = <package:("package" <PackageName> ";")?> <stmts:Spanned<Decl>*> => ast::Program { <> };

// Declarations
Decl = {
Expand Down Expand Up @@ -143,7 +143,7 @@ ExprS = Spanned<Expr>;
Expr = ExprAssign;

ExprAssign = {
<name:identifier> "=" <value:ExprS> =>
<name:QualifiedIdentifier> "=" <value:ExprS> =>
ast::Expr::Assign(Box::new(ast::ExprAssign {
identifier: ast::Identifier {
name,
Expand All @@ -155,7 +155,7 @@ ExprAssign = {
ast::Expr::SetIndex(Box::new(ast::ExprSetIndex {<>})),
<object:Spanned<ExprCall>> "." <name:identifier> "=" <value:ExprS> =>
ast::Expr::Set(Box::new(ast::ExprSet { <> })),
<object:Spanned<ExprCall>> "[" <name:identifier> "]" "=" <value:ExprS> =>
<object:Spanned<ExprCall>> "[" <name:QualifiedIdentifier> "]" "=" <value:ExprS> =>
ast::Expr::Set(Box::new(ast::ExprSet { <> })),
<object:Spanned<ExprCall>> "[" <name:string> "]" "=" <value:ExprS> =>
ast::Expr::Set(Box::new(ast::ExprSet { <> })),
Expand Down Expand Up @@ -218,7 +218,7 @@ ExprCall: ast::Expr = {
ast::Expr::Get(Box::new(ast::ExprGet { <> })),
<object:Spanned<ExprCall>> "[" <name:string> "]" =>
ast::Expr::Get(Box::new(ast::ExprGet { <> })),
<object:Spanned<ExprCall>> "[" <name:identifier> "]" =>
<object:Spanned<ExprCall>> "[" <name:QualifiedIdentifier> "]" =>
ast::Expr::Get(Box::new(ast::ExprGet { <> })),
<target:Spanned<ExprCall>> "[" <index:number> "]" =>
ast::Expr::GetIndex(Box::new(ast::ExprGetIndex {<>})),
Expand All @@ -238,7 +238,7 @@ ExprCall: ast::Expr = {
},
name,
}),
"super" "[" <name:identifier> "]" =>
"super" "[" <name:QualifiedIdentifier> "]" =>
ast::Expr::Super(ast::ExprSuper {
super_: ast::Identifier {
name: "super".to_string(),
Expand Down Expand Up @@ -270,7 +270,7 @@ ExprPrimary: ast::Expr = {
"(" <Expr> ")",
}

ExprIdentifier: ast::Expr = <name:identifier> =>
ExprIdentifier: ast::Expr = <name:QualifiedIdentifier> =>
ast::Expr::Identifier(ast::ExprIdentifier {
identifier: ast::Identifier {
name,
Expand All @@ -293,13 +293,26 @@ Spanned<T>: ast::Spanned<T> = <l:@L> <t:T> <r:@R> => (t, l..r);

// Comma separated list of string parameters a function/method takes
Params: Vec<String> = {
<first:identifier> <mut params:("," <identifier>)*> => {
<first:QualifiedIdentifier> <mut params:("," <QualifiedIdentifier>)*> => {
params.insert(0, first);
params
},
() => Vec::new(),
};

QualifiedIdentifier: String = {
<package:PackageName> ":" <id:identifier> => format!("{package}:{id}"),
<identifier> => <>
}

// Comma separated list of string parameters a function/method takes
PackageName: String = {
<first:identifier> <mut paths:("::"<identifier>)*> => {
paths.insert(0, first);
paths.join("::")
}
};

// Comma separated list of expression arugments passed to function/method calls
Args: Vec<ast::ExprS> = {
<first:ExprS> <mut args:("," <ExprS>)*> => {
Expand Down Expand Up @@ -329,6 +342,7 @@ extern {
"/" => lexer::Token::Slash,
"%" => lexer::Token::Modulus,
"*" => lexer::Token::Asterisk,
":" => lexer::Token::Colon,

// One or two character tokens.
"!" => lexer::Token::Bang,
Expand All @@ -340,6 +354,7 @@ extern {
"<" => lexer::Token::Less,
"<=" => lexer::Token::LessEqual,
"=>" => lexer::Token::FatArrow,
"::" => lexer::Token::DoubleColon,

// Literals.
identifier => lexer::Token::Identifier(<String>),
Expand All @@ -363,5 +378,6 @@ extern {
"let" => lexer::Token::Let,
"while" => lexer::Token::While,
"extends" => lexer::Token::Extends,
"package" => lexer::Token::Package,
}
}
1 change: 1 addition & 0 deletions src/syntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub type ExprS = Spanned<Expr>;

#[derive(Debug, Default)]
pub struct Program {
pub package: Option<String>,
pub stmts: Vec<StmtS>,
}

Expand Down
6 changes: 6 additions & 0 deletions src/syntax/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ pub enum Token {
Asterisk,
#[token("%")]
Modulus,
#[token(":")]
Colon,

// One or two character tokens.
#[token("!")]
Expand All @@ -110,6 +112,8 @@ pub enum Token {
LessEqual,
#[token("=>")]
FatArrow,
#[token("::")]
DoubleColon,

// Literals.
#[regex("[a-zA-Z_][a-zA-Z0-9_]*", lex_identifier)]
Expand Down Expand Up @@ -152,6 +156,8 @@ pub enum Token {
While,
#[token("extends")]
Extends,
#[token("package")]
Package,

#[regex(r"//.*", logos::skip)]
#[regex(r"[ \r\n\t\f]+", logos::skip)]
Expand Down
17 changes: 12 additions & 5 deletions src/vm/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,21 @@ impl Compiler {
pub fn compile(program: &Program, gc: &mut Gc) -> Result<*mut ObjectFunction, Vec<ErrorS>> {
let mut compiler = Self::new(gc);

if let Some(package_name) = &program.package {
let package_name = gc.alloc(package_name.to_owned()).into();

compiler.emit_u8(op::PACKAGE, &NO_SPAN);
let _ = compiler.emit_constant(package_name, &NO_SPAN);
}

for stmt in &program.stmts {
compiler.compile_stmt(stmt, gc).map_err(|e| vec![e])?;
}

if let Some(_) = &program.package {
compiler.emit_u8(op::POP, &NO_SPAN);
}

compiler.emit_u8(op::NIL, &NO_SPAN);
compiler.emit_u8(op::RETURN, &NO_SPAN);

Expand Down Expand Up @@ -514,11 +525,7 @@ impl Compiler {
};
}
Expr::Literal(literal) => match literal {
ExprLiteral::Bool(true) => {
println!("emitting true bool");

self.emit_u8(op::TRUE, span)
}
ExprLiteral::Bool(true) => self.emit_u8(op::TRUE, span),
ExprLiteral::Bool(false) => self.emit_u8(op::FALSE, span),
ExprLiteral::Nil => self.emit_u8(op::NIL, span),
ExprLiteral::Number(number) => {
Expand Down
1 change: 1 addition & 0 deletions src/vm/disassembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ impl<'a> Disassembler<'a> {
op::GET_INDEX => self.disassemble_op_simple("OP_GET_INDEX"),
op::SET_INDEX => self.disassemble_op_simple("OP_SET_INDEX"),
op::METHOD => self.disassemble_op_constant("OP_METHOD", op_idx),
op::PACKAGE => self.disassemble_op_constant("OP_PACKAGE", op_idx),
op::FIELD => self.disassemble_op_constant("OP_FIELD", op_idx),
byte => self.disassemble_op_simple(&format!("OP_UNKNOWN({byte:#X})")),
};
Expand Down
4 changes: 4 additions & 0 deletions src/vm/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ impl Gc {
self.mark(value);
}
}
ObjectType::Package => {
let package = unsafe { object.package };
self.mark(unsafe { (*package).name });
}
ObjectType::Upvalue => {
let upvalue = unsafe { object.upvalue };
self.mark(unsafe { (*upvalue).closed });
Expand Down
46 changes: 29 additions & 17 deletions src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::vm::allocator::GLOBAL;
use crate::vm::gc::GcAlloc;
use crate::vm::object::{
Native, ObjectBoundMethod, ObjectClass, ObjectClosure, ObjectFunction, ObjectInstance,
ObjectList, ObjectNative, ObjectString, ObjectType, ObjectUpvalue,
ObjectList, ObjectNative, ObjectPackage, ObjectString, ObjectType, ObjectUpvalue,
};
use crate::vm::value::Value;

Expand Down Expand Up @@ -193,6 +193,7 @@ impl VM {
op::CREATE_LIST => self.op_create_list(),
op::GET_INDEX => self.op_get_index(),
op::SET_INDEX => self.op_set_index(),
op::PACKAGE => self.op_package(),
_ => util::unreachable(),
}?;

Expand Down Expand Up @@ -265,6 +266,24 @@ impl VM {
Ok(())
}

fn op_package(&mut self) -> Result<()> {
let name = unsafe { self.read_value().as_object().string };

if cfg!(feature = "vm-trace") {
eprintln!("Pushing package on to stack");
}

let package = self.alloc(ObjectPackage::new(name)).into();

if cfg!(feature = "vm-trace") {
eprintln!("Pushed package on to stack");
}

self.push(package);

Ok(())
}

fn op_set_index(&mut self) -> Result<()> {
let value = self.pop();
let index = self.pop();
Expand Down Expand Up @@ -1143,23 +1162,14 @@ impl Default for VM {

let mut globals = HashMap::with_capacity_and_hasher(256, BuildHasherDefault::default());

globals.insert(gc.alloc("clock"), Value::from(gc.alloc(ObjectNative::new(Native::Clock))));
globals.insert(gc.alloc("len"), Value::from(gc.alloc(ObjectNative::new(Native::Length))));
globals.insert(gc.alloc("print"), Value::from(gc.alloc(ObjectNative::new(Native::Print))));
globals
.insert(gc.alloc("println"), Value::from(gc.alloc(ObjectNative::new(Native::PrintLn))));

let print_string = gc.alloc("print");
let print_native = Value::from(gc.alloc(ObjectNative::new(Native::Print)));
globals.insert(print_string, print_native);

let println_string = gc.alloc("println");
let println_native = Value::from(gc.alloc(ObjectNative::new(Native::PrintLn)));
globals.insert(println_string, println_native);

let init_string = gc.alloc("init");

Self {
globals.insert(gc.alloc("clock"), gc.alloc(ObjectNative::new(Native::Clock)).into());
globals.insert(gc.alloc("len"), gc.alloc(ObjectNative::new(Native::Length)).into());
globals.insert(gc.alloc("print"), gc.alloc(ObjectNative::new(Native::Print)).into());
globals.insert(gc.alloc("println"), gc.alloc(ObjectNative::new(Native::PrintLn)).into());

let vm = Self {
globals,
open_upvalues: Vec::with_capacity(256),
gc,
Expand All @@ -1174,7 +1184,9 @@ impl Default for VM {
stack_top: ptr::null_mut(),
init_string,
source: String::new(),
}
};

vm
}
}

Expand Down
26 changes: 26 additions & 0 deletions src/vm/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub union Object {
pub native: *mut ObjectNative,
pub string: *mut ObjectString,
pub list: *mut ObjectList,
pub package: *mut ObjectPackage,
pub upvalue: *mut ObjectUpvalue,
}

Expand Down Expand Up @@ -75,6 +76,11 @@ impl Object {
let _ = Box::from_raw(self.list);
};
}
ObjectType::Package => {
unsafe {
let _ = Box::from_raw(self.package);
};
}
ObjectType::Upvalue => {
unsafe {
let _ = Box::from_raw(self.upvalue);
Expand Down Expand Up @@ -146,6 +152,9 @@ impl Display for Object {
);
write!(f, "{}", v)
}
ObjectType::Package => {
write!(f, "<package {}>", unsafe { (*(*self.package).name).value })
}
ObjectType::Upvalue => write!(f, "<upvalue>"),
}
}
Expand All @@ -170,6 +179,7 @@ impl_from_object!(instance, ObjectInstance);
impl_from_object!(native, ObjectNative);
impl_from_object!(string, ObjectString);
impl_from_object!(list, ObjectList);
impl_from_object!(package, ObjectPackage);
impl_from_object!(upvalue, ObjectUpvalue);

impl PartialEq for Object {
Expand All @@ -196,6 +206,7 @@ pub enum ObjectType {
Instance,
String,
List,
Package,
Upvalue,
}

Expand All @@ -210,6 +221,7 @@ impl Display for ObjectType {
ObjectType::Native => write!(f, "native"),
ObjectType::String => write!(f, "string"),
ObjectType::List => write!(f, "list"),
ObjectType::Package => write!(f, "package"),
ObjectType::Upvalue => write!(f, "upvalue"),
}
}
Expand Down Expand Up @@ -358,6 +370,20 @@ impl ObjectList {
}
}

#[derive(Debug)]
#[repr(C)]
pub struct ObjectPackage {
pub common: ObjectCommon,
pub name: *mut ObjectString,
}

impl ObjectPackage {
pub fn new(name: *mut ObjectString) -> Self {
let common = ObjectCommon { type_: ObjectType::Package, is_marked: false };
Self { common, name }
}
}

#[derive(Debug)]
#[repr(C)]
pub struct ObjectUpvalue {
Expand Down
4 changes: 3 additions & 1 deletion src/vm/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,7 @@ iota! {
FIELD,
CREATE_LIST,
GET_INDEX,
SET_INDEX
SET_INDEX,
// Reads a 1 byte offset for the package name
PACKAGE
}
7 changes: 4 additions & 3 deletions src/vm/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,10 @@ mod tests {
assert_eq!(Value::from(0.0).type_(), ValueType::Number);
assert_eq!(Value::from(f64::NAN).type_(), ValueType::Number);
assert_eq!(
Value::from(
&mut ObjectCommon { type_: ObjectType::String, is_marked: false } as *mut _
)
Value::from(&mut ObjectCommon {
type_: ObjectType::String,
is_marked: false
} as *mut _)
.type_(),
ValueType::Object(ObjectType::String)
);
Expand Down
Loading

0 comments on commit 45ba9bc

Please sign in to comment.