Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions reference/Language.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,5 @@ Status of core JavaScript language features in GiavaScript.
## Notes

- This reflects current behavior in the interpreter and specs.
- `let` and `const` declarations return explicit errors: `Error: unsupported declaration 'let'` and `Error: unsupported declaration 'const'`.
- Use `var` for variable declarations.
2 changes: 2 additions & 0 deletions reference/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ Status of core JavaScript language features in GiavaScript.
### Notes

- This reflects current behavior in the interpreter and specs.
- `let` and `const` declarations return explicit errors: `Error: unsupported declaration 'let'` and `Error: unsupported declaration 'const'`.
- Use `var` for variable declarations.

## Type Methods and Properties

Expand Down
11 changes: 8 additions & 3 deletions spec/giavascript_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -1562,11 +1562,16 @@ describe GiavaScript do
interpreter.eval("continue;").should eq(["Error: continue can only be used inside loops"])
end

it "rejects let and const declarations" do
it "rejects let declarations with an explicit unsupported-declaration error" do
interpreter = GiavaScript::Interpreter.new

interpreter.eval("let value = 1;").should eq(["Error: invalid assignment target 'let value'"])
interpreter.eval("const total = 2;").should eq(["Error: invalid assignment target 'const total'"])
interpreter.eval("let value = 1;").should eq(["Error: unsupported declaration 'let'"])
end

it "rejects const declarations with an explicit unsupported-declaration error" do
interpreter = GiavaScript::Interpreter.new

interpreter.eval("const total = 2;").should eq(["Error: unsupported declaration 'const'"])
end

it "rejects class declarations" do
Expand Down
22 changes: 22 additions & 0 deletions src/giavascript/interpreter.cr
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ module GiavaScript
end
end

class UnsupportedDeclarationRawStatement < CompiledRawStatement
getter keyword : String

def initialize(@keyword : String)
end
end

def initialize(@console_output : IO = STDOUT)
@env = build_global_env
@function_runtime = FunctionRuntime.new
Expand Down Expand Up @@ -185,6 +192,10 @@ module GiavaScript
return "Error: return can only be used inside functions"
end

if keyword = unsupported_declaration_keyword(stmt)
return "Error: unsupported declaration '#{keyword}'"
end

if match = stmt.match(/^(.+?)\s*(\+\+|--)$/)
target_source = match[1].strip
operator = match[2]
Expand Down Expand Up @@ -811,6 +822,8 @@ module GiavaScript
rescue ex : ExpressionError
ex.message || "Error: invalid right-hand side '#{compiled.source}'"
end
when UnsupportedDeclarationRawStatement
"Error: unsupported declaration '#{compiled.keyword}'"
end
end

Expand Down Expand Up @@ -843,6 +856,8 @@ module GiavaScript
rescue
FallbackRawStatement.new(source)
end
elsif keyword = unsupported_declaration_keyword(key)
UnsupportedDeclarationRawStatement.new(keyword)
elsif assignment = split_assignment_statement(key)
begin
target = parse_assignment_target(assignment[:lhs])
Expand Down Expand Up @@ -948,6 +963,13 @@ module GiavaScript
next_char.nil? || !(next_char.ascii_letter? || next_char.ascii_number? || next_char == '_')
end

private def unsupported_declaration_keyword(source : String) : String?
return "let" if starts_with_keyword?(source, "let")
return "const" if starts_with_keyword?(source, "const")

nil
end

private def call_function(name : String, args : Array(Value), env : Environment) : Value
@function_runtime.invoke_function(name, args, env) do |stmt, local_env, inside_function, inside_loop|
eval_statement(stmt, local_env, inside_function, inside_loop)
Expand Down
Loading