feat: add list subscript set
This commit is contained in:
@@ -4,4 +4,21 @@ let a = [
|
|||||||
"c"
|
"c"
|
||||||
]
|
]
|
||||||
print(a)
|
print(a)
|
||||||
print(a[0])
|
print(a[0])
|
||||||
|
|
||||||
|
a[1] = "B"
|
||||||
|
|
||||||
|
print(a)
|
||||||
|
|
||||||
|
let l = [
|
||||||
|
["a", "b", "c"],
|
||||||
|
["1", "2", "3"]
|
||||||
|
]
|
||||||
|
|
||||||
|
print(l)
|
||||||
|
print(l[1][2])
|
||||||
|
|
||||||
|
l[1][2] = "three"
|
||||||
|
|
||||||
|
print(l)
|
||||||
|
print(l[1][2])
|
||||||
@@ -74,6 +74,10 @@ class Expr(ABC):
|
|||||||
def visit_set_expr(self, expr: SetExpr) -> T:
|
def visit_set_expr(self, expr: SetExpr) -> T:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def visit_subscript_set_expr(self, expr: SubscriptSetExpr) -> T:
|
||||||
|
...
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def visit_this_expr(self, expr: ThisExpr) -> T:
|
def visit_this_expr(self, expr: ThisExpr) -> T:
|
||||||
...
|
...
|
||||||
@@ -133,8 +137,8 @@ class GetExpr(Expr):
|
|||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class SubscriptGetExpr(Expr):
|
class SubscriptGetExpr(Expr):
|
||||||
object: Expr
|
object: Expr
|
||||||
bracket: Token
|
|
||||||
index: Expr
|
index: Expr
|
||||||
|
bracket: Token
|
||||||
|
|
||||||
def accept(self, visitor: Expr.Visitor[T]) -> T:
|
def accept(self, visitor: Expr.Visitor[T]) -> T:
|
||||||
return visitor.visit_subscript_get_expr(self)
|
return visitor.visit_subscript_get_expr(self)
|
||||||
@@ -214,6 +218,17 @@ class SetExpr(Expr):
|
|||||||
return visitor.visit_set_expr(self)
|
return visitor.visit_set_expr(self)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class SubscriptSetExpr(Expr):
|
||||||
|
object: Expr
|
||||||
|
index: Expr
|
||||||
|
bracket: Token
|
||||||
|
value: Expr
|
||||||
|
|
||||||
|
def accept(self, visitor: Expr.Visitor[T]) -> T:
|
||||||
|
return visitor.visit_subscript_set_expr(self)
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class ThisExpr(Expr):
|
class ThisExpr(Expr):
|
||||||
keyword: Token
|
keyword: Token
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class StringFormatter:
|
|||||||
return str(obj)
|
return str(obj)
|
||||||
if isinstance(obj, str) and quote_str:
|
if isinstance(obj, str) and quote_str:
|
||||||
return '"' + obj + '"'
|
return '"' + obj + '"'
|
||||||
return obj
|
return str(obj)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def assert_type(token: Token, obj: Any, expected_type: type | tuple[type, ...]):
|
def assert_type(token: Token, obj: Any, expected_type: type | tuple[type, ...]):
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ from enum import Enum, auto
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from src.ast.expr import Expr, VariableExpr, LiteralExpr, GroupingExpr, UnaryExpr, BinaryExpr, AssignExpr, LogicalExpr, \
|
from src.ast.expr import Expr, VariableExpr, LiteralExpr, GroupingExpr, UnaryExpr, BinaryExpr, AssignExpr, LogicalExpr, \
|
||||||
CallExpr, SetExpr, GetExpr, ThisExpr, SuperExpr, FStringExpr, FStringEmbedExpr, ListExpr, SubscriptGetExpr
|
CallExpr, SetExpr, GetExpr, ThisExpr, SuperExpr, FStringExpr, FStringEmbedExpr, ListExpr, SubscriptGetExpr, \
|
||||||
|
SubscriptSetExpr
|
||||||
from src.ast.stmt import Stmt, LetStmt, IfStmt, ExpressionStmt, BlockStmt, WhileStmt, ForStmt, FunctionStmt, \
|
from src.ast.stmt import Stmt, LetStmt, IfStmt, ExpressionStmt, BlockStmt, WhileStmt, ForStmt, FunctionStmt, \
|
||||||
ReturnStmt, BreakStmt, ContinueStmt, ClassStmt
|
ReturnStmt, BreakStmt, ContinueStmt, ClassStmt
|
||||||
from src.core.format_spec.spec import FormatSpec
|
from src.core.format_spec.spec import FormatSpec
|
||||||
@@ -44,6 +45,9 @@ class Formatter(Expr.Visitor[str], Stmt.Visitor[str]):
|
|||||||
def visit_set_expr(self, expr: SetExpr) -> str:
|
def visit_set_expr(self, expr: SetExpr) -> str:
|
||||||
return f"{self.format(expr.object)}.{expr.name.lexeme} = {self.format(expr.value)}"
|
return f"{self.format(expr.object)}.{expr.name.lexeme} = {self.format(expr.value)}"
|
||||||
|
|
||||||
|
def visit_subscript_set_expr(self, expr: SubscriptSetExpr) -> str:
|
||||||
|
return f"{self.format(expr.object)}[{self.format(expr.index)}] = {self.format(expr.value)}"
|
||||||
|
|
||||||
def visit_this_expr(self, expr: ThisExpr) -> str:
|
def visit_this_expr(self, expr: ThisExpr) -> str:
|
||||||
return expr.keyword.lexeme
|
return expr.keyword.lexeme
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from src.ast.expr import LiteralExpr, GroupingExpr, UnaryExpr, BinaryExpr, Expr, VariableExpr, AssignExpr, LogicalExpr, \
|
from src.ast.expr import LiteralExpr, GroupingExpr, UnaryExpr, BinaryExpr, Expr, VariableExpr, AssignExpr, LogicalExpr, \
|
||||||
CallExpr, GetExpr, SetExpr, ThisExpr, SuperExpr, FStringExpr, FStringEmbedExpr, ListExpr, SubscriptGetExpr
|
CallExpr, GetExpr, SetExpr, ThisExpr, SuperExpr, FStringExpr, FStringEmbedExpr, ListExpr, SubscriptGetExpr, \
|
||||||
|
SubscriptSetExpr
|
||||||
from src.ast.stmt import Stmt, ExpressionStmt, LetStmt, BlockStmt, IfStmt, WhileStmt, ForStmt, FunctionStmt, \
|
from src.ast.stmt import Stmt, ExpressionStmt, LetStmt, BlockStmt, IfStmt, WhileStmt, ForStmt, FunctionStmt, \
|
||||||
ReturnStmt, BreakStmt, ContinueStmt, ClassStmt
|
ReturnStmt, BreakStmt, ContinueStmt, ClassStmt
|
||||||
from src.consts import CONSTRUCTOR_NAME
|
from src.consts import CONSTRUCTOR_NAME
|
||||||
@@ -90,6 +91,14 @@ class Interpreter(Expr.Visitor[Any], Stmt.Visitor[None]):
|
|||||||
obj.set(expr.name, value)
|
obj.set(expr.name, value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def visit_subscript_set_expr(self, expr: SubscriptSetExpr) -> Any:
|
||||||
|
obj: Any = self.evaluate(expr.object)
|
||||||
|
if not isinstance(obj, PebbleList):
|
||||||
|
raise PebbleRuntimeError(expr.bracket, "Only lists can be indexed.")
|
||||||
|
value: Any = self.evaluate(expr.value)
|
||||||
|
idx: Any = self.evaluate(expr.index)
|
||||||
|
obj.set(idx, value, expr.bracket)
|
||||||
|
|
||||||
def visit_this_expr(self, expr: ThisExpr) -> Any:
|
def visit_this_expr(self, expr: ThisExpr) -> Any:
|
||||||
return self.look_up_variable(expr.keyword, expr)
|
return self.look_up_variable(expr.keyword, expr)
|
||||||
|
|
||||||
@@ -177,10 +186,10 @@ class Interpreter(Expr.Visitor[Any], Stmt.Visitor[None]):
|
|||||||
|
|
||||||
def visit_subscript_get_expr(self, expr: SubscriptGetExpr) -> Any:
|
def visit_subscript_get_expr(self, expr: SubscriptGetExpr) -> Any:
|
||||||
obj: Any = self.evaluate(expr.object)
|
obj: Any = self.evaluate(expr.object)
|
||||||
|
if not isinstance(obj, PebbleList):
|
||||||
|
raise PebbleRuntimeError(expr.bracket, "Only lists can be indexed.")
|
||||||
idx: Any = self.evaluate(expr.index)
|
idx: Any = self.evaluate(expr.index)
|
||||||
if isinstance(obj, PebbleList):
|
return obj.get(idx, expr.bracket)
|
||||||
return obj.get(idx, expr.bracket)
|
|
||||||
raise PebbleRuntimeError(expr.bracket, "Only lists can be indexed.")
|
|
||||||
|
|
||||||
def visit_grouping_expr(self, expr: GroupingExpr) -> Any:
|
def visit_grouping_expr(self, expr: GroupingExpr) -> Any:
|
||||||
return self.evaluate(expr.expression)
|
return self.evaluate(expr.expression)
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ from enum import Enum, auto
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from src.ast.expr import Expr, LogicalExpr, VariableExpr, LiteralExpr, GroupingExpr, CallExpr, UnaryExpr, BinaryExpr, \
|
from src.ast.expr import Expr, LogicalExpr, VariableExpr, LiteralExpr, GroupingExpr, CallExpr, UnaryExpr, BinaryExpr, \
|
||||||
AssignExpr, GetExpr, SetExpr, ThisExpr, SuperExpr, FStringExpr, FStringEmbedExpr, ListExpr, SubscriptGetExpr
|
AssignExpr, GetExpr, SetExpr, ThisExpr, SuperExpr, FStringExpr, FStringEmbedExpr, ListExpr, SubscriptGetExpr, \
|
||||||
|
SubscriptSetExpr
|
||||||
from src.ast.stmt import Stmt, ForStmt, WhileStmt, LetStmt, ReturnStmt, IfStmt, FunctionStmt, \
|
from src.ast.stmt import Stmt, ForStmt, WhileStmt, LetStmt, ReturnStmt, IfStmt, FunctionStmt, \
|
||||||
ExpressionStmt, BlockStmt, BreakStmt, ContinueStmt, ClassStmt
|
ExpressionStmt, BlockStmt, BreakStmt, ContinueStmt, ClassStmt
|
||||||
from src.consts import CONSTRUCTOR_NAME
|
from src.consts import CONSTRUCTOR_NAME
|
||||||
@@ -134,6 +135,11 @@ class Resolver(Expr.Visitor[None], Stmt.Visitor[None]):
|
|||||||
self.resolve(expr.value)
|
self.resolve(expr.value)
|
||||||
self.resolve(expr.object)
|
self.resolve(expr.object)
|
||||||
|
|
||||||
|
def visit_subscript_set_expr(self, expr: SubscriptSetExpr) -> None:
|
||||||
|
self.resolve(expr.value)
|
||||||
|
self.resolve(expr.object)
|
||||||
|
self.resolve(expr.index)
|
||||||
|
|
||||||
def visit_this_expr(self, expr: ThisExpr) -> None:
|
def visit_this_expr(self, expr: ThisExpr) -> None:
|
||||||
if self.current_class == ClassType.NONE:
|
if self.current_class == ClassType.NONE:
|
||||||
Pebble.token_error(expr.keyword, "Cannot use 'this' outside of a class.")
|
Pebble.token_error(expr.keyword, "Cannot use 'this' outside of a class.")
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from src.ast.expr import Expr, BinaryExpr, UnaryExpr, LiteralExpr, GroupingExpr, VariableExpr, AssignExpr, LogicalExpr, \
|
from src.ast.expr import Expr, BinaryExpr, UnaryExpr, LiteralExpr, GroupingExpr, VariableExpr, AssignExpr, LogicalExpr, \
|
||||||
CallExpr, GetExpr, SetExpr, ThisExpr, SuperExpr, FStringExpr, FStringEmbedExpr, ListExpr, SubscriptGetExpr
|
CallExpr, GetExpr, SetExpr, ThisExpr, SuperExpr, FStringExpr, FStringEmbedExpr, ListExpr, SubscriptGetExpr, \
|
||||||
|
SubscriptSetExpr
|
||||||
from src.ast.stmt import Stmt, ExpressionStmt, LetStmt, BlockStmt, IfStmt, WhileStmt, ForStmt, FunctionStmt, \
|
from src.ast.stmt import Stmt, ExpressionStmt, LetStmt, BlockStmt, IfStmt, WhileStmt, ForStmt, FunctionStmt, \
|
||||||
ReturnStmt, BreakStmt, ContinueStmt, ClassStmt
|
ReturnStmt, BreakStmt, ContinueStmt, ClassStmt
|
||||||
from src.consts import MAX_FUNCTION_ARGS
|
from src.consts import MAX_FUNCTION_ARGS
|
||||||
@@ -275,6 +276,9 @@ class Parser:
|
|||||||
|
|
||||||
elif isinstance(expr, GetExpr):
|
elif isinstance(expr, GetExpr):
|
||||||
return SetExpr(expr.object, expr.name, value)
|
return SetExpr(expr.object, expr.name, value)
|
||||||
|
|
||||||
|
elif isinstance(expr, SubscriptGetExpr):
|
||||||
|
return SubscriptSetExpr(expr.object, expr.index, expr.bracket, value)
|
||||||
self.error(operator, "Invalid assignment target.")
|
self.error(operator, "Invalid assignment target.")
|
||||||
return expr
|
return expr
|
||||||
|
|
||||||
@@ -363,7 +367,7 @@ class Parser:
|
|||||||
while self.match(TokenType.LEFT_BRACKET):
|
while self.match(TokenType.LEFT_BRACKET):
|
||||||
idx: Expr = self.expression()
|
idx: Expr = self.expression()
|
||||||
bracket: Token = self.consume(TokenType.RIGHT_BRACKET, "Unclosed list index")
|
bracket: Token = self.consume(TokenType.RIGHT_BRACKET, "Unclosed list index")
|
||||||
expr = SubscriptGetExpr(expr, bracket, idx)
|
expr = SubscriptGetExpr(expr, idx, bracket)
|
||||||
return expr
|
return expr
|
||||||
|
|
||||||
def primary(self) -> Expr:
|
def primary(self) -> Expr:
|
||||||
|
|||||||
Reference in New Issue
Block a user