diff --git a/playground/src/pages/docs.tsx b/playground/src/pages/docs.tsx index 31510fb..11d75d3 100644 --- a/playground/src/pages/docs.tsx +++ b/playground/src/pages/docs.tsx @@ -134,8 +134,13 @@ const Docs: React.FC = () => (
  • - - Inheritance + + Class Inheritance + +
  • +
  • + + Class Field/Method Index Access
  • @@ -413,8 +418,8 @@ const Docs: React.FC = () => ( height="300px" /> ( height="400px" /> + +

    Errors{' '} diff --git a/res/examples/field/index_access_get_method_on_instance.locks b/res/examples/field/index_access_get_method_on_instance.locks new file mode 100644 index 0000000..06378d5 --- /dev/null +++ b/res/examples/field/index_access_get_method_on_instance.locks @@ -0,0 +1,15 @@ +class Box { + let value; + + fn init(value) { + this.value = value; + } + + fn get() { + return this.value; + } +} + +let box = Box(123); + +print box["get"](); // out: 123 diff --git a/res/examples/field/index_access_get_nested.locks b/res/examples/field/index_access_get_nested.locks new file mode 100644 index 0000000..aa1fcc1 --- /dev/null +++ b/res/examples/field/index_access_get_nested.locks @@ -0,0 +1,23 @@ +class Object { + let box; + + fn init(value) { + this.box = Box(value); + } +} + +class Box { + let value; + + fn init(value) { + this.value = value; + } + + fn get() { + return this.value; + } +} + +let obj = Object(123); + +print obj["box"]["get"](); // out: 123 diff --git a/res/examples/field/index_access_get_set_on_super.locks b/res/examples/field/index_access_get_set_on_super.locks new file mode 100644 index 0000000..c9e3c71 --- /dev/null +++ b/res/examples/field/index_access_get_set_on_super.locks @@ -0,0 +1,25 @@ +class Parent { + let value; + + fn init(value) { + this["value"] = value; + } + + fn get() { + return this["value"]; + } +} + +class Child extends Parent { + fn init(value) { + super["init"](value); + } + + fn get() { + return this.value; + } +} + +let child = Child(123); + +print child.get(); // out: 123 diff --git a/res/examples/field/index_access_get_set_on_this.locks b/res/examples/field/index_access_get_set_on_this.locks new file mode 100644 index 0000000..d20fa46 --- /dev/null +++ b/res/examples/field/index_access_get_set_on_this.locks @@ -0,0 +1,15 @@ +class Box { + let value; + + fn init(value) { + this["value"] = value; + } + + fn get() { + return this["value"]; + } +} + +let box = Box(123); + +print box.get(); // out: 123 diff --git a/res/examples/field/index_access_get_undefined.locks b/res/examples/field/index_access_get_undefined.locks new file mode 100644 index 0000000..63fe391 --- /dev/null +++ b/res/examples/field/index_access_get_undefined.locks @@ -0,0 +1,6 @@ +class Object { +} + +let obj = Object(); + +print obj["key"]; // out: AttributeError: "Object" object has no attribute "key" diff --git a/res/examples/field/index_access_set_method_on_instance.locks b/res/examples/field/index_access_set_method_on_instance.locks new file mode 100644 index 0000000..76a8bdf --- /dev/null +++ b/res/examples/field/index_access_set_method_on_instance.locks @@ -0,0 +1,15 @@ +class Box { + let value; + + fn init(value) { + this.value = value; + } + + fn get() { + return this.value; + } +} + +let box = Box(123); + +box["get"] = 123; // out: TypeError: methods on instances can not be reassigned (e.g. instance.get = "...") diff --git a/res/examples/field/index_access_set_undefined.locks b/res/examples/field/index_access_set_undefined.locks new file mode 100644 index 0000000..2241c7f --- /dev/null +++ b/res/examples/field/index_access_set_undefined.locks @@ -0,0 +1,6 @@ +class Object { +} + +let obj = Object(); + +obj["key"] = "new value"; // out: AttributeError: "Object" object has no attribute "key" diff --git a/res/examples/field/index_access_with_expr.locks b/res/examples/field/index_access_with_expr.locks new file mode 100644 index 0000000..c84f293 --- /dev/null +++ b/res/examples/field/index_access_with_expr.locks @@ -0,0 +1,12 @@ +class Record { + let key = "value"; +} + +let key = "key"; +let record = Record(); + +print record[key]; // out: value + +record[key] = "new value"; + +print record[key]; // out: new value diff --git a/res/examples/field/index_access_with_string.locks b/res/examples/field/index_access_with_string.locks new file mode 100644 index 0000000..af20249 --- /dev/null +++ b/res/examples/field/index_access_with_string.locks @@ -0,0 +1,11 @@ +class Record { + let key = "value"; +} + +let record = Record(); + +print record["key"]; // out: value + +record["key"] = "new value"; + +print record["key"]; // out: new value diff --git a/res/grammar.lalrpop b/res/grammar.lalrpop index 6415e4a..f5ea2e6 100644 --- a/res/grammar.lalrpop +++ b/res/grammar.lalrpop @@ -121,6 +121,10 @@ ExprAssign = { })), > "." "=" => ast::Expr::Set(Box::new(ast::ExprSet { <> })), + > "[" "]" "=" => + ast::Expr::Set(Box::new(ast::ExprSet { <> })), + > "[" "]" "=" => + ast::Expr::Set(Box::new(ast::ExprSet { <> })), ExprLogicOr, } @@ -172,6 +176,10 @@ ExprCall: ast::Expr = { ast::Expr::Call(Box::new(ast::ExprCall { callee, args })), > "." => ast::Expr::Get(Box::new(ast::ExprGet { <> })), + > "[" "]" => + ast::Expr::Get(Box::new(ast::ExprGet { <> })), + > "[" "]" => + ast::Expr::Get(Box::new(ast::ExprGet { <> })), "super" "." => ast::Expr::Super(ast::ExprSuper { super_: ast::Identifier { @@ -180,6 +188,22 @@ ExprCall: ast::Expr = { }, name, }), + "super" "[" "]" => + ast::Expr::Super(ast::ExprSuper { + super_: ast::Identifier { + name: "super".to_string(), + depth: None, + }, + name, + }), + "super" "[" "]" => + ast::Expr::Super(ast::ExprSuper { + super_: ast::Identifier { + name: "super".to_string(), + depth: None, + }, + name, + }), ExprPrimary, } @@ -253,6 +277,8 @@ extern { ")" => lexer::Token::RtParen, "{" => lexer::Token::LtBrace, "}" => lexer::Token::RtBrace, + "[" => lexer::Token::LtBracket, + "]" => lexer::Token::RtBracket, "," => lexer::Token::Comma, "." => lexer::Token::Dot, "-" => lexer::Token::Minus, diff --git a/src/syntax/lexer.rs b/src/syntax/lexer.rs index 53bca35..e26137c 100644 --- a/src/syntax/lexer.rs +++ b/src/syntax/lexer.rs @@ -70,6 +70,10 @@ pub enum Token { LtBrace, #[token("}")] RtBrace, + #[token("[")] + LtBracket, + #[token("]")] + RtBracket, #[token(",")] Comma, #[token(".")] diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 2aeeb41..407026b 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -788,10 +788,6 @@ impl VM { /// Create a new [`ObjectInstance`] of an [`ObjectClass`]. /// /// Calls the `init` method if it exists on the [`ObjectClass`]. - /// - /// ``` - /// let instance = Class(); - /// ``` fn call_class(&mut self, class: *mut ObjectClass, arg_count: usize) -> Result<()> { let instance = self.alloc(ObjectInstance::new(class));