├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── asset ├── index.scss ├── mustache │ ├── contents-nav.html │ ├── contents-part.html │ ├── contents.html │ ├── footer.html │ ├── header.html │ ├── in_design.html │ ├── index.html │ ├── nav.html │ ├── page.html │ └── prev-next.html ├── sass │ ├── chapter.scss │ ├── contents.scss │ ├── print.scss │ ├── shared.scss │ └── sign-up.scss └── style.scss ├── book ├── a-bytecode-virtual-machine.md ├── a-map-of-the-territory.md ├── a-tree-walk-interpreter.md ├── a-virtual-machine.md ├── acknowledgements.md ├── appendix-i.md ├── appendix-ii.md ├── backmatter.md ├── calls-and-functions.md ├── chunks-of-bytecode.md ├── classes-and-instances.md ├── classes.md ├── closures.md ├── compiling-expressions.md ├── contents.md ├── control-flow.md ├── dedication.md ├── evaluating-expressions.md ├── functions.md ├── garbage-collection.md ├── global-variables.md ├── hash-tables.md ├── index.md ├── inheritance.md ├── introduction.md ├── jumping-back-and-forth.md ├── local-variables.md ├── methods-and-initializers.md ├── optimization.md ├── parsing-expressions.md ├── representing-code.md ├── resolving-and-binding.md ├── scanning-on-demand.md ├── scanning.md ├── statements-and-state.md ├── strings.md ├── superclasses.md ├── the-lox-language.md ├── types-of-values.md └── welcome.md ├── c ├── chunk.c ├── chunk.h ├── clox.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── clox.xcscheme ├── common.h ├── compiler.c ├── compiler.h ├── debug.c ├── debug.h ├── main.c ├── memory.c ├── memory.h ├── object.c ├── object.h ├── scanner.c ├── scanner.h ├── table.c ├── table.h ├── value.c ├── value.h ├── vm.c └── vm.h ├── java └── com │ └── craftinginterpreters │ ├── lox │ ├── AstPrinter.java │ ├── Environment.java │ ├── Expr.java │ ├── Interpreter.java │ ├── Lox.java │ ├── LoxCallable.java │ ├── LoxClass.java │ ├── LoxFunction.java │ ├── LoxInstance.java │ ├── Parser.java │ ├── Resolver.java │ ├── Return.java │ ├── RuntimeError.java │ ├── Scanner.java │ ├── Stmt.java │ ├── Token.java │ └── TokenType.java │ └── tool │ └── GenerateAst.java ├── jlox ├── note ├── BISAC.txt ├── answers │ ├── chapter01_introduction │ │ ├── 2 │ │ │ ├── Hello.java │ │ │ └── Makefile │ │ ├── 3 │ │ │ ├── Makefile │ │ │ ├── linked_list │ │ │ ├── linked_list.c │ │ │ └── linked_list.xcodeproj │ │ │ │ ├── project.pbxproj │ │ │ │ └── project.xcworkspace │ │ │ │ └── contents.xcworkspacedata │ │ └── 1.md │ ├── chapter02_map.md │ ├── chapter03_lox.md │ ├── chapter04_scanning.md │ ├── chapter05_representing.md │ ├── chapter06_parsing.md │ ├── chapter07_evaluating.md │ ├── chapter08_statements.md │ ├── chapter09_control.md │ ├── chapter10_functions.md │ ├── chapter11_resolving │ │ ├── 4 │ │ │ └── com │ │ │ │ └── craftinginterpreters │ │ │ │ ├── lox │ │ │ │ ├── AstPrinter.java │ │ │ │ ├── Environment.java │ │ │ │ ├── Expr.java │ │ │ │ ├── Interpreter.java │ │ │ │ ├── Lox.java │ │ │ │ ├── LoxCallable.java │ │ │ │ ├── LoxFunction.java │ │ │ │ ├── Parser.java │ │ │ │ ├── Resolver.java │ │ │ │ ├── Return.java │ │ │ │ ├── RuntimeError.java │ │ │ │ ├── Scanner.java │ │ │ │ ├── Stmt.java │ │ │ │ ├── Token.java │ │ │ │ └── TokenType.java │ │ │ │ └── tool │ │ │ │ └── GenerateAst.java │ │ └── chapter11_resolving.md │ ├── chapter12_classes.md │ ├── chapter13_inheritance │ │ ├── 1.md │ │ ├── 2.md │ │ └── 3.md │ ├── chapter14_chunks │ │ ├── 1.md │ │ └── 2.md │ ├── chapter15_virtual │ │ ├── 1.md │ │ ├── 2.md │ │ └── 3.md │ ├── chapter16_scanning.md │ ├── chapter17_compiling.md │ ├── chapter18_types.md │ ├── chapter19_strings.md │ ├── chapter20_hash │ │ └── 1.md │ ├── chapter21_global.md │ ├── chapter23_jumping │ │ ├── 1.md │ │ ├── 2.md │ │ └── 3.md │ ├── chapter24_calls │ │ ├── 1.md │ │ └── 2.md │ ├── chapter25_closures │ │ ├── 1.md │ │ ├── 2.md │ │ └── 3.lox │ ├── chapter26_garbage │ │ ├── 1.md │ │ └── 2.md │ ├── chapter27_classes │ │ ├── 1.md │ │ ├── 2.md │ │ ├── 3.md │ │ └── 4.md │ ├── chapter28_methods │ │ ├── 1.md │ │ ├── 2.md │ │ └── 3.md │ └── chapter29_superclasses │ │ ├── 1.md │ │ ├── 2.md │ │ ├── 3.diff │ │ └── 3.md ├── blurb.txt ├── contents.txt ├── design breaks.md ├── images.md ├── indexing.md ├── log.txt ├── names.txt ├── objects.txt ├── outline.md ├── research.txt ├── scope.txt ├── struct sizes.txt ├── style guide.md └── todo.txt ├── site ├── .htaccess ├── 404.html ├── a-bytecode-virtual-machine.html ├── a-map-of-the-territory.html ├── a-tree-walk-interpreter.html ├── a-virtual-machine.html ├── acknowledgements.html ├── appendix-i.html ├── appendix-ii.html ├── backmatter.html ├── calls-and-functions.html ├── chunks-of-bytecode.html ├── classes-and-instances.html ├── classes.html ├── closures.html ├── columns.png ├── compiling-expressions.html ├── contents.html ├── control-flow.html ├── dedication.html ├── evaluating-expressions.html ├── font │ ├── crimson-bold.woff │ ├── crimson-bolditalic.woff │ ├── crimson-italic.woff │ ├── crimson-roman.woff │ ├── crimson-semibold.woff │ └── crimson-semibolditalic.woff ├── functions.html ├── garbage-collection.html ├── global-variables.html ├── hash-tables.html ├── image │ ├── a-map-of-the-territory │ │ ├── ast.png │ │ ├── mountain.png │ │ ├── plants.png │ │ ├── string.png │ │ ├── tokens.png │ │ └── venn.png │ ├── a-virtual-machine │ │ ├── array.png │ │ ├── ast.png │ │ ├── bars-stacked.png │ │ ├── bars.png │ │ ├── chunk.png │ │ ├── pancakes.png │ │ ├── reverse.png │ │ ├── stack-c.png │ │ ├── stack-crepe.png │ │ └── stack-empty.png │ ├── background.png │ ├── calls-and-functions │ │ ├── argument-stack.png │ │ ├── arithmetic.png │ │ ├── calls.png │ │ ├── overlapping-windows.png │ │ ├── parameter-window.png │ │ ├── return.png │ │ └── window.png │ ├── chunks-of-bytecode │ │ ├── ast.png │ │ ├── format.png │ │ ├── grow.png │ │ ├── insert.png │ │ └── phases.png │ ├── classes-and-instances │ │ ├── klass.png │ │ ├── lox-clox.png │ │ └── stack.png │ ├── classes │ │ ├── bound-method.png │ │ ├── call.png │ │ ├── circle.png │ │ ├── closure.png │ │ ├── method.png │ │ ├── setter.png │ │ └── zip.png │ ├── closures │ │ ├── closing.png │ │ ├── execution-flow.png │ │ ├── flying.png │ │ ├── linked-list.png │ │ ├── linked-upvalues.png │ │ ├── obj-closure.png │ │ ├── open-upvalue.png │ │ └── recursion.png │ ├── compiling-expressions │ │ ├── calls.png │ │ ├── connections.png │ │ ├── keyhole.png │ │ ├── mystery.png │ │ ├── pipeline.png │ │ └── points-to.png │ ├── control-flow │ │ ├── dangling-else.png │ │ ├── sugar.png │ │ └── turing-machine.png │ ├── dogshot.jpg │ ├── evaluating-expressions │ │ ├── lightning.png │ │ ├── muffin.png │ │ └── skeleton.png │ ├── favicon.png │ ├── format-ebook.jpg │ ├── format-pdf.jpg │ ├── format-print.jpg │ ├── format-web.jpg │ ├── functions │ │ ├── binding.png │ │ ├── body.png │ │ ├── closure.png │ │ ├── foreign.png │ │ ├── global.png │ │ ├── lambda.png │ │ └── recursion.png │ ├── garbage-collection │ │ ├── baguette.png │ │ ├── black.png │ │ ├── gray.png │ │ ├── latency-throughput.png │ │ ├── mark-sweep.png │ │ ├── reachable.png │ │ ├── recycle.png │ │ ├── stack.png │ │ ├── tricolor-trace.png │ │ ├── unlink.png │ │ └── white.png │ ├── ginny.png │ ├── global-variables │ │ ├── ast-bad.png │ │ ├── ast-good.png │ │ ├── setter.png │ │ └── stack-effect.png │ ├── hash-tables │ │ ├── bucket-array.png │ │ ├── chaining.png │ │ ├── collision.png │ │ ├── delete-1.png │ │ ├── delete-2.png │ │ ├── delete-3.png │ │ ├── insert-1.png │ │ ├── insert-2.png │ │ ├── insert-3.png │ │ ├── insert-4.png │ │ ├── insert-5.png │ │ ├── insert-6.png │ │ ├── insert-7.png │ │ ├── pigeons.png │ │ └── tombstone.png │ ├── header-small.png │ ├── header.png │ ├── inheritance │ │ ├── classes.png │ │ ├── doughnuts.png │ │ ├── environments.png │ │ ├── superclass.png │ │ └── superhero.png │ ├── introduction │ │ ├── bootstrap.png │ │ ├── little-languages.png │ │ └── yak.png │ ├── jumping-back-and-forth │ │ ├── and.png │ │ ├── bad-else.png │ │ ├── for.png │ │ ├── full-if-else.png │ │ ├── if-else.png │ │ ├── if-without-else.png │ │ ├── or.png │ │ ├── patch.png │ │ └── while.png │ ├── local-variables │ │ ├── block.png │ │ ├── declaration.png │ │ ├── local-slots.png │ │ ├── phases.png │ │ └── scopes.png │ ├── logotype.png │ ├── methods-and-initializers │ │ ├── benchmark.png │ │ ├── bind-method.png │ │ ├── closure-slot.png │ │ ├── init-call-frame.png │ │ ├── method-instructions.png │ │ └── party-hat.png │ ├── optimization │ │ ├── bools.png │ │ ├── double.png │ │ ├── hash-chart.png │ │ ├── mask.png │ │ ├── nan.png │ │ ├── nil.png │ │ ├── obj.png │ │ ├── qnan.png │ │ └── union.png │ ├── parsing-expressions │ │ ├── direction.png │ │ ├── panic.png │ │ ├── sequence.png │ │ ├── syntax-trees.png │ │ └── tokens.png │ ├── representing-code │ │ ├── breakfast.png │ │ ├── columns.png │ │ ├── expression.png │ │ ├── rows.png │ │ ├── table.png │ │ ├── tree-evaluate.png │ │ └── visitor.png │ ├── resolving-and-binding │ │ ├── environment-1.png │ │ ├── environment-2.png │ │ ├── environment-3.png │ │ ├── environment-4.png │ │ ├── environment-5.png │ │ └── split.png │ ├── scanning-on-demand │ │ ├── axolotl.png │ │ ├── fields.png │ │ ├── keywords.png │ │ ├── numbers.png │ │ └── pipeline.png │ ├── scanning │ │ ├── lexemes.png │ │ └── lexigator.png │ ├── statements-and-state │ │ ├── blocks.png │ │ ├── brain.png │ │ ├── cactus.png │ │ ├── chaining.png │ │ └── environment.png │ ├── strings │ │ ├── obj.png │ │ ├── pstring.png │ │ ├── stack.png │ │ ├── value.png │ │ └── viola.png │ ├── superclasses │ │ ├── clox-resolve.png │ │ ├── inherit-stack.png │ │ ├── jlox-resolve.png │ │ ├── monkey.png │ │ ├── super-instructions.png │ │ └── super-invoke.png │ ├── the-lox-language │ │ ├── class-lookup.png │ │ └── prototype-lookup.png │ ├── types-of-values │ │ ├── memcmp.png │ │ ├── struct.png │ │ ├── union.png │ │ ├── universe.png │ │ └── value.png │ └── wood.jpg ├── index.css ├── index.css.map ├── index.html ├── inheritance.html ├── introduction.html ├── jquery-3.4.1.min.js ├── jumping-back-and-forth.html ├── local-variables.html ├── methods-and-initializers.html ├── optimization.html ├── parsing-expressions.html ├── representing-code.html ├── resolving-and-binding.html ├── rows-22.png ├── rows.png ├── sample.pdf ├── scanning-on-demand.html ├── scanning.html ├── script.js ├── statements-and-state.html ├── strings.html ├── style.css ├── style.css.map ├── superclasses.html ├── the-lox-language.html ├── types-of-values.html └── welcome.html ├── test ├── assignment │ ├── associativity.lox │ ├── global.lox │ ├── grouping.lox │ ├── infix_operator.lox │ ├── local.lox │ ├── prefix_operator.lox │ ├── syntax.lox │ ├── to_this.lox │ └── undefined.lox ├── benchmark │ ├── binary_trees.lox │ ├── equality.lox │ ├── fib.lox │ ├── instantiation.lox │ ├── invocation.lox │ ├── method_call.lox │ ├── properties.lox │ ├── string_equality.lox │ ├── trees.lox │ ├── zoo.lox │ └── zoo_batch.lox ├── block │ ├── empty.lox │ └── scope.lox ├── bool │ ├── equality.lox │ └── not.lox ├── call │ ├── bool.lox │ ├── nil.lox │ ├── num.lox │ ├── object.lox │ └── string.lox ├── class │ ├── empty.lox │ ├── inherit_self.lox │ ├── inherited_method.lox │ ├── local_inherit_other.lox │ ├── local_inherit_self.lox │ ├── local_reference_self.lox │ └── reference_self.lox ├── closure │ ├── assign_to_closure.lox │ ├── assign_to_shadowed_later.lox │ ├── close_over_function_parameter.lox │ ├── close_over_later_variable.lox │ ├── close_over_method_parameter.lox │ ├── closed_closure_in_function.lox │ ├── nested_closure.lox │ ├── open_closure_in_function.lox │ ├── reference_closure_multiple_times.lox │ ├── reuse_closure_slot.lox │ ├── shadow_closure_with_local.lox │ ├── unused_closure.lox │ └── unused_later_closure.lox ├── comments │ ├── line_at_eof.lox │ ├── only_line_comment.lox │ ├── only_line_comment_and_line.lox │ └── unicode.lox ├── constructor ├── empty_file.lox ├── expressions │ ├── evaluate.lox │ └── parse.lox ├── field │ ├── call_function_field.lox │ ├── call_nonfunction_field.lox │ ├── get_and_set_method.lox │ ├── get_on_bool.lox │ ├── get_on_class.lox │ ├── get_on_function.lox │ ├── get_on_nil.lox │ ├── get_on_num.lox │ ├── get_on_string.lox │ ├── many.lox │ ├── method.lox │ ├── method_binds_this.lox │ ├── on_instance.lox │ ├── set_evaluation_order.lox │ ├── set_on_bool.lox │ ├── set_on_class.lox │ ├── set_on_function.lox │ ├── set_on_nil.lox │ ├── set_on_num.lox │ ├── set_on_string.lox │ └── undefined.lox ├── for │ ├── class_in_body.lox │ ├── closure_in_body.lox │ ├── fun_in_body.lox │ ├── return_closure.lox │ ├── return_inside.lox │ ├── scope.lox │ ├── statement_condition.lox │ ├── statement_increment.lox │ ├── statement_initializer.lox │ ├── syntax.lox │ └── var_in_body.lox ├── function │ ├── body_must_be_block.lox │ ├── empty_body.lox │ ├── extra_arguments.lox │ ├── local_mutual_recursion.lox │ ├── local_recursion.lox │ ├── missing_arguments.lox │ ├── missing_comma_in_parameters.lox │ ├── mutual_recursion.lox │ ├── nested_call_with_arguments.lox │ ├── parameters.lox │ ├── print.lox │ ├── recursion.lox │ ├── too_many_arguments.lox │ └── too_many_parameters.lox ├── if │ ├── class_in_else.lox │ ├── class_in_then.lox │ ├── dangling_else.lox │ ├── else.lox │ ├── fun_in_else.lox │ ├── fun_in_then.lox │ ├── if.lox │ ├── truth.lox │ ├── var_in_else.lox │ └── var_in_then.lox ├── inheritance │ ├── constructor.lox │ ├── inherit_from_function.lox │ ├── inherit_from_nil.lox │ ├── inherit_from_number.lox │ ├── inherit_methods.lox │ ├── parenthesized_superclass.lox │ └── set_fields_from_base_class.lox ├── limit │ ├── loop_too_large.lox │ ├── no_reuse_constants.lox │ ├── stack_overflow.lox │ ├── too_many_constants.lox │ ├── too_many_locals.lox │ └── too_many_upvalues.lox ├── logical_operator │ ├── and.lox │ ├── and_truth.lox │ ├── or.lox │ └── or_truth.lox ├── method │ ├── arity.lox │ ├── empty_block.lox │ ├── extra_arguments.lox │ ├── missing_arguments.lox │ ├── not_found.lox │ ├── print_bound_method.lox │ ├── refer_to_name.lox │ ├── too_many_arguments.lox │ └── too_many_parameters.lox ├── nil │ └── literal.lox ├── number │ ├── decimal_point_at_eof.lox │ ├── leading_dot.lox │ ├── literals.lox │ ├── nan_equality.lox │ └── trailing_dot.lox ├── operator │ ├── add.lox │ ├── add_bool_nil.lox │ ├── add_bool_num.lox │ ├── add_bool_string.lox │ ├── add_nil_nil.lox │ ├── add_num_nil.lox │ ├── add_string_nil.lox │ ├── comparison.lox │ ├── divide.lox │ ├── divide_nonnum_num.lox │ ├── divide_num_nonnum.lox │ ├── equals.lox │ ├── equals_class.lox │ ├── equals_method.lox │ ├── greater_nonnum_num.lox │ ├── greater_num_nonnum.lox │ ├── greater_or_equal_nonnum_num.lox │ ├── greater_or_equal_num_nonnum.lox │ ├── less_nonnum_num.lox │ ├── less_num_nonnum.lox │ ├── less_or_equal_nonnum_num.lox │ ├── less_or_equal_num_nonnum.lox │ ├── multiply.lox │ ├── multiply_nonnum_num.lox │ ├── multiply_num_nonnum.lox │ ├── negate.lox │ ├── negate_nonnum.lox │ ├── not.lox │ ├── not_class.lox │ ├── not_equals.lox │ ├── subtract.lox │ ├── subtract_nonnum_num.lox │ └── subtract_num_nonnum.lox ├── precedence.lox ├── print │ └── missing_argument.lox ├── regression │ ├── 394.lox │ └── 40.lox ├── return │ ├── after_else.lox │ ├── after_if.lox │ ├── after_while.lox │ ├── at_top_level.lox │ ├── in_function.lox │ ├── in_method.lox │ └── return_nil_if_no_value.lox ├── scanning │ ├── identifiers.lox │ ├── keywords.lox │ ├── numbers.lox │ ├── punctuators.lox │ ├── strings.lox │ └── whitespace.lox ├── string │ ├── error_after_multiline.lox │ ├── literals.lox │ ├── multiline.lox │ └── unterminated.lox ├── super │ ├── bound_method.lox │ ├── call_other_method.lox │ ├── call_same_method.lox │ ├── closure.lox │ ├── constructor.lox │ ├── extra_arguments.lox │ ├── indirectly_inherited.lox │ ├── missing_arguments.lox │ ├── no_superclass_bind.lox │ ├── no_superclass_call.lox │ ├── no_superclass_method.lox │ ├── parenthesized.lox │ ├── reassign_superclass.lox │ ├── super_at_top_level.lox │ ├── super_in_closure_in_inherited_method.lox │ ├── super_in_inherited_method.lox │ ├── super_in_top_level_function.lox │ ├── super_without_dot.lox │ ├── super_without_name.lox │ └── this_in_superclass_method.lox ├── this │ ├── closure.lox │ ├── nested_class.lox │ ├── nested_closure.lox │ ├── this_at_top_level.lox │ ├── this_in_method.lox │ └── this_in_top_level_function.lox ├── unexpected_character.lox ├── variable │ ├── collide_with_parameter.lox │ ├── duplicate_local.lox │ ├── duplicate_parameter.lox │ ├── early_bound.lox │ ├── in_middle_of_block.lox │ ├── in_nested_block.lox │ ├── local_from_method.lox │ ├── redeclare_global.lox │ ├── redefine_global.lox │ ├── scope_reuse_in_different_blocks.lox │ ├── shadow_and_local.lox │ ├── shadow_global.lox │ ├── shadow_local.lox │ ├── undefined_global.lox │ ├── undefined_local.lox │ ├── uninitialized.lox │ ├── unreached_undefined.lox │ ├── use_false_as_var.lox │ ├── use_global_in_initializer.lox │ ├── use_local_in_initializer.lox │ ├── use_nil_as_var.lox │ └── use_this_as_var.lox └── while │ ├── class_in_body.lox │ ├── closure_in_body.lox │ ├── fun_in_body.lox │ ├── return_closure.lox │ ├── return_inside.lox │ ├── syntax.lox │ └── var_in_body.lox ├── tool ├── analysis_options.yaml ├── bin │ ├── benchmark.dart │ ├── build.dart │ ├── build_xml.dart │ ├── compile_snippets.dart │ ├── split_chapters.dart │ ├── test.dart │ └── tile_pages.dart ├── lib │ └── src │ │ ├── book.dart │ │ ├── code_tag.dart │ │ ├── format.dart │ │ ├── location.dart │ │ ├── markdown │ │ ├── block_syntax.dart │ │ ├── code_syntax.dart │ │ ├── html_renderer.dart │ │ ├── inline_syntax.dart │ │ ├── markdown.dart │ │ └── xml_renderer.dart │ │ ├── mustache.dart │ │ ├── page.dart │ │ ├── page_parser.dart │ │ ├── snippet.dart │ │ ├── source_file_parser.dart │ │ ├── split_chapter.dart │ │ ├── syntax │ │ ├── grammar.dart │ │ ├── highlighter.dart │ │ ├── language.dart │ │ └── rule.dart │ │ ├── term.dart │ │ └── text.dart ├── pubspec.lock └── pubspec.yaml └── util ├── c.make ├── intellij ├── chap04_read.iml ├── chap05_scanning.iml ├── chap06_representing.iml ├── chap07_parsing.iml ├── chap08_evaluating.iml ├── chap09_statements.iml ├── chap10_control.iml ├── chap11_functions.iml ├── chap12_resolving.iml ├── chap13_classes.iml ├── chap14_inheritance.iml ├── intellij.iml ├── jlox.iml ├── section_test.iml └── snippet_test.iml └── java.make /.gitignore: -------------------------------------------------------------------------------- 1 | # Intermediate and built stuff. 2 | .sass-cache/ 3 | /build/ 4 | /gen/ 5 | clox 6 | *.class 7 | exercises/chapter01_introduction/3/linked_list 8 | .idea/ 9 | 10 | # I keep a scratch file at the top level to try stuff out. 11 | temp.lox 12 | 13 | # XCode user-specific stuff. 14 | xcuserdata/ 15 | 16 | # Dart stuff. 17 | /tool/.dart_tool/ 18 | /tool/.packages 19 | -------------------------------------------------------------------------------- /asset/mustache/contents-nav.html: -------------------------------------------------------------------------------- 1 |

  Table of Contents

2 | 8 | {{> prev-next }} 9 | -------------------------------------------------------------------------------- /asset/mustache/contents-part.html: -------------------------------------------------------------------------------- 1 |

{{ number }}.{{ title }}

2 | -------------------------------------------------------------------------------- /asset/mustache/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /asset/mustache/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{title}} · Crafting Interpreters 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /asset/mustache/in_design.html: -------------------------------------------------------------------------------- 1 | 2 | {{ number }} 3 | {{ title }} 4 | {{ part }} 5 | {{{ body }}} 6 | 7 | -------------------------------------------------------------------------------- /asset/mustache/nav.html: -------------------------------------------------------------------------------- 1 | {{# is_chapter }} 2 |

{{ title }}{{ number }}

3 | 4 | 18 | 19 | {{/ is_chapter }} 20 | {{# is_part }} 21 |

{{ number }}{{ title }}

22 | 23 | 28 | 29 | {{/ is_part }} 30 | {{# is_frontmatter }} 31 |

{{ number }}{{ title }}

32 |
33 | {{/ is_frontmatter }} 34 | 35 | {{> prev-next }} -------------------------------------------------------------------------------- /asset/mustache/prev-next.html: -------------------------------------------------------------------------------- 1 |
2 | {{# has_prev }} 3 | ← Previous 4 | {{/ has_prev }} 5 | {{# has_up }} 6 | ↑ Up 7 | {{/ has_up }} 8 | {{# has_next }} 9 | Next → 10 | {{/ has_next }} 11 |
-------------------------------------------------------------------------------- /asset/sass/sign-up.scss: -------------------------------------------------------------------------------- 1 | .sign-up { 2 | padding: 12px; 3 | margin: 24px 0 24px 0; 4 | background: hsl(40, 80%, 95%); 5 | color: hsl(40, 50%, 50%); 6 | border-radius: 3px; 7 | 8 | form { 9 | display: flex; 10 | } 11 | 12 | input { 13 | padding: 4px; 14 | font: 16px $nav; 15 | outline: none; 16 | border-radius: 3px; 17 | border: solid 2px hsl(40, 100%, 75%); 18 | color: hsl(40, 70%, 30%); 19 | height: 32px; 20 | } 21 | 22 | input.email { 23 | display: block; 24 | box-sizing: border-box; 25 | width: 100%; 26 | } 27 | 28 | input.button { 29 | margin-left: 8px; 30 | padding: 4px 8px; 31 | font: 600 13px $nav; 32 | text-transform: uppercase; 33 | letter-spacing: 1px; 34 | background: hsl(40, 100%, 60%); 35 | border: none; 36 | 37 | transition: background-color 0.2s ease; 38 | } 39 | 40 | input.button:hover { 41 | background: hsl(40, 100%, 75%); 42 | } 43 | 44 | input:focus { 45 | border-color: hsl(40, 100%, 50%); 46 | } 47 | } -------------------------------------------------------------------------------- /book/a-bytecode-virtual-machine.md: -------------------------------------------------------------------------------- 1 | Our Java interpreter, jlox, taught us many of the fundamentals of programming 2 | languages, but we still have much to learn. First, if you run any interesting 3 | Lox programs in jlox, you'll discover it's achingly slow. The style of 4 | interpretation it uses -- walking the AST directly -- is good enough for *some* 5 | real-world uses, but leaves a lot to be desired for a general-purpose scripting 6 | language. 7 | 8 | Also, we implicitly rely on runtime features of the JVM itself. We take for 9 | granted that things like `instanceof` in Java work *somehow*. And we never for a 10 | second worry about memory management because the JVM's garbage collector takes 11 | care of it for us. 12 | 13 | When we were focused on high-level concepts, it was fine to gloss over those. 14 | But now that we know our way around an interpreter, it's time to dig down to 15 | those lower layers and build our own virtual machine from scratch using nothing 16 | more than the C standard library... 17 | -------------------------------------------------------------------------------- /book/a-tree-walk-interpreter.md: -------------------------------------------------------------------------------- 1 | With this part, we begin jlox, the first of our two interpreters. Programming 2 | languages are a huge topic with piles of concepts and terminology to cram into 3 | your brain all at once. Programming language theory requires a level of mental 4 | rigor that you probably haven't had to summon since your last calculus final. 5 | (Fortunately there isn't too much theory in this book.) 6 | 7 | Implementing an interpreter uses a few architectural tricks and design 8 | patterns uncommon in other kinds of applications, so we'll be getting used to 9 | the engineering side of things too. Given all of that, we'll keep the code we 10 | have to write as simple and plain as possible. 11 | 12 | In less than two thousand lines of clean Java code, we'll build a complete 13 | interpreter for Lox that implements every single feature of the language, 14 | exactly as we've specified. The first few chapters work front-to-back through 15 | the phases of the interpreter -- [scanning][], [parsing][], and 16 | [evaluating code][]. After that, we add language features one at a time, 17 | growing a simple calculator into a full-fledged scripting language. 18 | 19 | [scanning]: scanning.html 20 | [parsing]: parsing-expressions.html 21 | [evaluating code]: evaluating-expressions.html 22 | -------------------------------------------------------------------------------- /book/backmatter.md: -------------------------------------------------------------------------------- 1 | You've reached the end of the book! There are two pieces of supplementary 2 | material you may find helpful: 3 | 4 | * **[Appendix I][]** contains a complete grammar for Lox, all in one place. 5 | 6 | * **[Appendix II][]** shows the Java classes produced by [the AST generator][] 7 | we use for jlox. 8 | 9 | [appendix i]: appendix-i.html 10 | [appendix ii]: appendix-ii.html 11 | [the ast generator]: representing-code.html#metaprogramming-the-trees 12 | -------------------------------------------------------------------------------- /book/contents.md: -------------------------------------------------------------------------------- 1 | This text is not used. All of the content is in the contents.html template. 2 | -------------------------------------------------------------------------------- /book/dedication.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | My beloved dog and her stupid face. 4 | 5 | To Ginny, I miss your stupid face. 6 | 7 |
-------------------------------------------------------------------------------- /book/index.md: -------------------------------------------------------------------------------- 1 | This text is not used. All of the content is in the index.html template. 2 | -------------------------------------------------------------------------------- /book/welcome.md: -------------------------------------------------------------------------------- 1 | This may be the beginning of a grand adventure. Programming languages encompass 2 | a huge space to explore and play in. Plenty of room for your own creations to 3 | share with others or just enjoy yourself. Brilliant computer scientists and 4 | software engineers have spent entire careers traversing this land without ever 5 | reaching the end. If this book is your first entry into the country, welcome. 6 | 7 | The pages of this book give you a guided tour through some of the world of 8 | languages. But before we strap on our hiking boots and venture out, we should 9 | familiarize ourselves with the territory. The chapters in this part introduce 10 | you to the basic concepts used by programming languages and how those concepts 11 | are organized. 12 | 13 | We will also get acquainted with Lox, the language we'll spend the rest of the 14 | book implementing (twice). 15 | -------------------------------------------------------------------------------- /c/clox.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /c/clox.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /c/clox.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /c/common.h: -------------------------------------------------------------------------------- 1 | //> Chunks of Bytecode common-h 2 | #ifndef clox_common_h 3 | #define clox_common_h 4 | 5 | #include 6 | #include 7 | #include 8 | //> A Virtual Machine define-debug-trace 9 | 10 | //> Optimization define-nan-boxing 11 | #define NAN_BOXING 12 | //< Optimization define-nan-boxing 13 | //> Compiling Expressions define-debug-print-code 14 | #define DEBUG_PRINT_CODE 15 | //< Compiling Expressions define-debug-print-code 16 | #define DEBUG_TRACE_EXECUTION 17 | //< A Virtual Machine define-debug-trace 18 | //> Garbage Collection define-stress-gc 19 | 20 | #define DEBUG_STRESS_GC 21 | //< Garbage Collection define-stress-gc 22 | //> Garbage Collection define-log-gc 23 | #define DEBUG_LOG_GC 24 | //< Garbage Collection define-log-gc 25 | //> Local Variables uint8-count 26 | 27 | #define UINT8_COUNT (UINT8_MAX + 1) 28 | //< Local Variables uint8-count 29 | 30 | #endif 31 | //> omit 32 | // In the book, we show them defined, but for working on them locally, 33 | // we don't want them to be. 34 | #undef DEBUG_PRINT_CODE 35 | #undef DEBUG_TRACE_EXECUTION 36 | #undef DEBUG_STRESS_GC 37 | #undef DEBUG_LOG_GC 38 | //< omit 39 | -------------------------------------------------------------------------------- /c/compiler.h: -------------------------------------------------------------------------------- 1 | //> Scanning on Demand compiler-h 2 | #ifndef clox_compiler_h 3 | #define clox_compiler_h 4 | 5 | //> Strings compiler-include-object 6 | #include "object.h" 7 | //< Strings compiler-include-object 8 | //> Compiling Expressions compile-h 9 | #include "vm.h" 10 | 11 | //< Compiling Expressions compile-h 12 | /* Scanning on Demand compiler-h < Compiling Expressions compile-h 13 | void compile(const char* source); 14 | */ 15 | /* Compiling Expressions compile-h < Calls and Functions compile-h 16 | bool compile(const char* source, Chunk* chunk); 17 | */ 18 | //> Calls and Functions compile-h 19 | ObjFunction* compile(const char* source); 20 | //< Calls and Functions compile-h 21 | //> Garbage Collection mark-compiler-roots-h 22 | void markCompilerRoots(); 23 | //< Garbage Collection mark-compiler-roots-h 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /c/debug.h: -------------------------------------------------------------------------------- 1 | //> Chunks of Bytecode debug-h 2 | #ifndef clox_debug_h 3 | #define clox_debug_h 4 | 5 | #include "chunk.h" 6 | 7 | void disassembleChunk(Chunk* chunk, const char* name); 8 | int disassembleInstruction(Chunk* chunk, int offset); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /c/memory.h: -------------------------------------------------------------------------------- 1 | //> Chunks of Bytecode memory-h 2 | #ifndef clox_memory_h 3 | #define clox_memory_h 4 | 5 | #include "common.h" 6 | //> Strings memory-include-object 7 | #include "object.h" 8 | //< Strings memory-include-object 9 | 10 | //> Strings allocate 11 | #define ALLOCATE(type, count) \ 12 | (type*)reallocate(NULL, 0, sizeof(type) * (count)) 13 | //> free 14 | 15 | #define FREE(type, pointer) reallocate(pointer, sizeof(type), 0) 16 | //< free 17 | 18 | //< Strings allocate 19 | #define GROW_CAPACITY(capacity) \ 20 | ((capacity) < 8 ? 8 : (capacity) * 2) 21 | //> grow-array 22 | 23 | #define GROW_ARRAY(type, pointer, oldCount, newCount) \ 24 | (type*)reallocate(pointer, sizeof(type) * (oldCount), \ 25 | sizeof(type) * (newCount)) 26 | //> free-array 27 | 28 | #define FREE_ARRAY(type, pointer, oldCount) \ 29 | reallocate(pointer, sizeof(type) * (oldCount), 0) 30 | //< free-array 31 | 32 | void* reallocate(void* pointer, size_t oldSize, size_t newSize); 33 | //< grow-array 34 | //> Garbage Collection mark-object-h 35 | void markObject(Obj* object); 36 | //< Garbage Collection mark-object-h 37 | //> Garbage Collection mark-value-h 38 | void markValue(Value value); 39 | //< Garbage Collection mark-value-h 40 | //> Garbage Collection collect-garbage-h 41 | void collectGarbage(); 42 | //< Garbage Collection collect-garbage-h 43 | //> Strings free-objects-h 44 | void freeObjects(); 45 | //< Strings free-objects-h 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /c/scanner.h: -------------------------------------------------------------------------------- 1 | //> Scanning on Demand scanner-h 2 | #ifndef clox_scanner_h 3 | #define clox_scanner_h 4 | //> token-type 5 | 6 | typedef enum { 7 | // Single-character tokens. 8 | TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN, 9 | TOKEN_LEFT_BRACE, TOKEN_RIGHT_BRACE, 10 | TOKEN_COMMA, TOKEN_DOT, TOKEN_MINUS, TOKEN_PLUS, 11 | TOKEN_SEMICOLON, TOKEN_SLASH, TOKEN_STAR, 12 | // One or two character tokens. 13 | TOKEN_BANG, TOKEN_BANG_EQUAL, 14 | TOKEN_EQUAL, TOKEN_EQUAL_EQUAL, 15 | TOKEN_GREATER, TOKEN_GREATER_EQUAL, 16 | TOKEN_LESS, TOKEN_LESS_EQUAL, 17 | // Literals. 18 | TOKEN_IDENTIFIER, TOKEN_STRING, TOKEN_NUMBER, 19 | // Keywords. 20 | TOKEN_AND, TOKEN_CLASS, TOKEN_ELSE, TOKEN_FALSE, 21 | TOKEN_FOR, TOKEN_FUN, TOKEN_IF, TOKEN_NIL, TOKEN_OR, 22 | TOKEN_PRINT, TOKEN_RETURN, TOKEN_SUPER, TOKEN_THIS, 23 | TOKEN_TRUE, TOKEN_VAR, TOKEN_WHILE, 24 | 25 | TOKEN_ERROR, TOKEN_EOF 26 | } TokenType; 27 | //< token-type 28 | //> token-struct 29 | 30 | typedef struct { 31 | TokenType type; 32 | const char* start; 33 | int length; 34 | int line; 35 | } Token; 36 | //< token-struct 37 | 38 | void initScanner(const char* source); 39 | //> scan-token-h 40 | Token scanToken(); 41 | //< scan-token-h 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /c/table.h: -------------------------------------------------------------------------------- 1 | //> Hash Tables table-h 2 | #ifndef clox_table_h 3 | #define clox_table_h 4 | 5 | #include "common.h" 6 | #include "value.h" 7 | //> entry 8 | 9 | typedef struct { 10 | ObjString* key; 11 | Value value; 12 | } Entry; 13 | //< entry 14 | 15 | typedef struct { 16 | int count; 17 | int capacity; 18 | Entry* entries; 19 | } Table; 20 | 21 | //> init-table-h 22 | void initTable(Table* table); 23 | //> free-table-h 24 | void freeTable(Table* table); 25 | //< free-table-h 26 | //> table-get-h 27 | bool tableGet(Table* table, ObjString* key, Value* value); 28 | //< table-get-h 29 | //> table-set-h 30 | bool tableSet(Table* table, ObjString* key, Value value); 31 | //< table-set-h 32 | //> table-delete-h 33 | bool tableDelete(Table* table, ObjString* key); 34 | //< table-delete-h 35 | //> table-add-all-h 36 | void tableAddAll(Table* from, Table* to); 37 | //< table-add-all-h 38 | //> table-find-string-h 39 | ObjString* tableFindString(Table* table, const char* chars, 40 | int length, uint32_t hash); 41 | //< table-find-string-h 42 | //> Garbage Collection table-remove-white-h 43 | 44 | void tableRemoveWhite(Table* table); 45 | //< Garbage Collection table-remove-white-h 46 | //> Garbage Collection mark-table-h 47 | void markTable(Table* table); 48 | //< Garbage Collection mark-table-h 49 | 50 | //< init-table-h 51 | #endif 52 | -------------------------------------------------------------------------------- /java/com/craftinginterpreters/lox/LoxCallable.java: -------------------------------------------------------------------------------- 1 | //> Functions callable 2 | package com.craftinginterpreters.lox; 3 | 4 | import java.util.List; 5 | 6 | interface LoxCallable { 7 | //> callable-arity 8 | int arity(); 9 | //< callable-arity 10 | Object call(Interpreter interpreter, List arguments); 11 | } 12 | -------------------------------------------------------------------------------- /java/com/craftinginterpreters/lox/LoxInstance.java: -------------------------------------------------------------------------------- 1 | //> Classes lox-instance 2 | package com.craftinginterpreters.lox; 3 | 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | class LoxInstance { 8 | private LoxClass klass; 9 | //> lox-instance-fields 10 | private final Map fields = new HashMap<>(); 11 | //< lox-instance-fields 12 | 13 | LoxInstance(LoxClass klass) { 14 | this.klass = klass; 15 | } 16 | 17 | //> lox-instance-get-property 18 | Object get(Token name) { 19 | if (fields.containsKey(name.lexeme)) { 20 | return fields.get(name.lexeme); 21 | } 22 | 23 | //> lox-instance-get-method 24 | LoxFunction method = klass.findMethod(name.lexeme); 25 | /* Classes lox-instance-get-method < Classes lox-instance-bind-method 26 | if (method != null) return method; 27 | */ 28 | //> lox-instance-bind-method 29 | if (method != null) return method.bind(this); 30 | //< lox-instance-bind-method 31 | 32 | //< lox-instance-get-method 33 | throw new RuntimeError(name, // [hidden] 34 | "Undefined property '" + name.lexeme + "'."); 35 | } 36 | //< lox-instance-get-property 37 | //> lox-instance-set-property 38 | void set(Token name, Object value) { 39 | fields.put(name.lexeme, value); 40 | } 41 | //< lox-instance-set-property 42 | @Override 43 | public String toString() { 44 | return klass.name + " instance"; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /java/com/craftinginterpreters/lox/Return.java: -------------------------------------------------------------------------------- 1 | //> Functions return-exception 2 | package com.craftinginterpreters.lox; 3 | 4 | class Return extends RuntimeException { 5 | final Object value; 6 | 7 | Return(Object value) { 8 | super(null, null, false, false); 9 | this.value = value; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /java/com/craftinginterpreters/lox/RuntimeError.java: -------------------------------------------------------------------------------- 1 | //> Evaluating Expressions runtime-error-class 2 | package com.craftinginterpreters.lox; 3 | 4 | class RuntimeError extends RuntimeException { 5 | final Token token; 6 | 7 | RuntimeError(Token token, String message) { 8 | super(message); 9 | this.token = token; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /java/com/craftinginterpreters/lox/Token.java: -------------------------------------------------------------------------------- 1 | //> Scanning token-class 2 | package com.craftinginterpreters.lox; 3 | 4 | class Token { 5 | final TokenType type; 6 | final String lexeme; 7 | final Object literal; 8 | final int line; // [location] 9 | 10 | Token(TokenType type, String lexeme, Object literal, int line) { 11 | this.type = type; 12 | this.lexeme = lexeme; 13 | this.literal = literal; 14 | this.line = line; 15 | } 16 | 17 | public String toString() { 18 | return type + " " + lexeme + " " + literal; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /java/com/craftinginterpreters/lox/TokenType.java: -------------------------------------------------------------------------------- 1 | //> Scanning token-type 2 | package com.craftinginterpreters.lox; 3 | 4 | enum TokenType { 5 | // Single-character tokens. 6 | LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, RIGHT_BRACE, 7 | COMMA, DOT, MINUS, PLUS, SEMICOLON, SLASH, STAR, 8 | 9 | // One or two character tokens. 10 | BANG, BANG_EQUAL, 11 | EQUAL, EQUAL_EQUAL, 12 | GREATER, GREATER_EQUAL, 13 | LESS, LESS_EQUAL, 14 | 15 | // Literals. 16 | IDENTIFIER, STRING, NUMBER, 17 | 18 | // Keywords. 19 | AND, CLASS, ELSE, FALSE, FUN, FOR, IF, NIL, OR, 20 | PRINT, RETURN, SUPER, THIS, TRUE, VAR, WHILE, 21 | 22 | EOF 23 | } 24 | -------------------------------------------------------------------------------- /jlox: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | script_dir=$(dirname "$0") 4 | java -cp ${script_dir}/build/java com.craftinginterpreters.lox.Lox $@ 5 | -------------------------------------------------------------------------------- /note/BISAC.txt: -------------------------------------------------------------------------------- 1 | COMPUTERS / Programming / Compilers 2 | COMPUTERS / Languages / General 3 | COMPUTERS / Software Development & Engineering / Tools -------------------------------------------------------------------------------- /note/answers/chapter01_introduction/1.md: -------------------------------------------------------------------------------- 1 | Markdown, Jinja2, Makefile, SASS, CSS, HTML. There's also the homegrown little 2 | tags inserted in the code and Markdown to weave the two together. 3 | 4 | The tests used to ensure the interpreters work correctly also have a 5 | mini-language embedded in comments to define expectations for how the test 6 | should behave. 7 | 8 | This doesn't count the Python scripts that glue this altogether, since Python 9 | is a general-purpose language. 10 | -------------------------------------------------------------------------------- /note/answers/chapter01_introduction/2/Hello.java: -------------------------------------------------------------------------------- 1 | public class Hello { 2 | public static void main(String[] args) { 3 | System.out.println("Hello, world!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /note/answers/chapter01_introduction/2/Makefile: -------------------------------------------------------------------------------- 1 | # Compile the Java file to a class file. 2 | Hello.class: Hello.java 3 | @ javac Hello.java 4 | 5 | # Convenience target to build and run it. 6 | run: Hello.class 7 | @ java Hello 8 | 9 | # Tell make that "run" is not the name of a file. 10 | .PHONY: run 11 | -------------------------------------------------------------------------------- /note/answers/chapter01_introduction/3/Makefile: -------------------------------------------------------------------------------- 1 | # Compile the .c file to an executable. 2 | linked_list: linked_list.c 3 | gcc linked_list.c -o linked_list 4 | -------------------------------------------------------------------------------- /note/answers/chapter01_introduction/3/linked_list: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/note/answers/chapter01_introduction/3/linked_list -------------------------------------------------------------------------------- /note/answers/chapter01_introduction/3/linked_list.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /note/answers/chapter02_map.md: -------------------------------------------------------------------------------- 1 | ## 1. Find the various parts in an open source implementation. 2 | 3 | TODO 4 | 5 | ## 2. Why not use a JIT? 6 | 7 | 1. It's really complex to implement, debug, and maintain. Few people have the 8 | skill to do it. 9 | 2. Like a native code compiler (which it is), it ties you to a specific CPU 10 | architecture. 11 | 3. Bytecode is generally more compact than machine code (since it's closer to 12 | the semantics of the language), so it takes up less memory. In platforms 13 | like embedded devices where memory may matter more than speed, that can be 14 | a worthwhile trade-off. 15 | 4. Some platforms, like iOS and most game consoles, expressly disallow 16 | executing code generated at runtime. The OS simply won't allow you to jump 17 | into memory that can be written to. 18 | 19 | ## 3. Why do Lisp compilers also contain an interpreter? 20 | 21 | Most Lisps support macros -- code that is executed at compile time, so the 22 | implementation needs to be able to evaluate the macro itself while in the middle 23 | of compiling. You could do that by *compiling* the macro and then running that, 24 | but that's a lot of overhead. 25 | -------------------------------------------------------------------------------- /note/answers/chapter11_resolving/4/com/craftinginterpreters/lox/Environment.java: -------------------------------------------------------------------------------- 1 | package com.craftinginterpreters.lox; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | class Environment { 7 | final Environment enclosing; 8 | private final List values = new ArrayList<>(); 9 | 10 | Environment() { 11 | enclosing = null; 12 | } 13 | 14 | Environment(Environment enclosing) { 15 | this.enclosing = enclosing; 16 | } 17 | 18 | void define(Object value) { 19 | values.add(value); 20 | } 21 | 22 | Object getAt(int distance, int slot) { 23 | Environment environment = this; 24 | for (int i = 0; i < distance; i++) { 25 | environment = environment.enclosing; 26 | } 27 | 28 | return environment.values.get(slot); 29 | } 30 | 31 | void assignAt(int distance, int slot, Object value) { 32 | Environment environment = this; 33 | for (int i = 0; i < distance; i++) { 34 | environment = environment.enclosing; 35 | } 36 | 37 | environment.values.set(slot, value); 38 | } 39 | @Override 40 | public String toString() { 41 | String result = values.toString(); 42 | if (enclosing != null) { 43 | result += " -> " + enclosing.toString(); 44 | } 45 | 46 | return result; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /note/answers/chapter11_resolving/4/com/craftinginterpreters/lox/LoxCallable.java: -------------------------------------------------------------------------------- 1 | package com.craftinginterpreters.lox; 2 | 3 | import java.util.List; 4 | 5 | interface LoxCallable { 6 | int arity(); 7 | Object call(Interpreter interpreter, List arguments); 8 | } 9 | -------------------------------------------------------------------------------- /note/answers/chapter11_resolving/4/com/craftinginterpreters/lox/LoxFunction.java: -------------------------------------------------------------------------------- 1 | package com.craftinginterpreters.lox; 2 | 3 | import java.util.List; 4 | 5 | class LoxFunction implements LoxCallable { 6 | private final Stmt.Function declaration; 7 | private final Environment closure; 8 | 9 | LoxFunction(Stmt.Function declaration, Environment closure) { 10 | this.closure = closure; 11 | this.declaration = declaration; 12 | } 13 | @Override 14 | public String toString() { 15 | return ""; 16 | } 17 | @Override 18 | public int arity() { 19 | return declaration.parameters.size(); 20 | } 21 | @Override 22 | public Object call(Interpreter interpreter, List arguments) { 23 | Environment environment = new Environment(closure); 24 | for (int i = 0; i < declaration.parameters.size(); i++) { 25 | environment.define(arguments.get(i)); 26 | } 27 | 28 | try { 29 | interpreter.executeBlock(declaration.body, environment); 30 | } catch (Return returnValue) { 31 | return returnValue.value; 32 | } 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /note/answers/chapter11_resolving/4/com/craftinginterpreters/lox/Return.java: -------------------------------------------------------------------------------- 1 | package com.craftinginterpreters.lox; 2 | 3 | class Return extends RuntimeException { 4 | final Object value; 5 | 6 | Return(Object value) { 7 | super(null, null, false, false); 8 | this.value = value; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /note/answers/chapter11_resolving/4/com/craftinginterpreters/lox/RuntimeError.java: -------------------------------------------------------------------------------- 1 | package com.craftinginterpreters.lox; 2 | 3 | class RuntimeError extends RuntimeException { 4 | final Token token; 5 | 6 | RuntimeError(Token token, String message) { 7 | super(message); 8 | this.token = token; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /note/answers/chapter11_resolving/4/com/craftinginterpreters/lox/Token.java: -------------------------------------------------------------------------------- 1 | package com.craftinginterpreters.lox; 2 | 3 | class Token { 4 | final TokenType type; 5 | final String lexeme; 6 | final Object literal; 7 | final int line; // [location] 8 | 9 | Token(TokenType type, String lexeme, Object literal, int line) { 10 | this.type = type; 11 | this.lexeme = lexeme; 12 | this.literal = literal; 13 | this.line = line; 14 | } 15 | 16 | public String toString() { 17 | return type + " " + lexeme + " " + literal; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /note/answers/chapter11_resolving/4/com/craftinginterpreters/lox/TokenType.java: -------------------------------------------------------------------------------- 1 | package com.craftinginterpreters.lox; 2 | 3 | enum TokenType { 4 | // Single-character tokens. 5 | LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, RIGHT_BRACE, 6 | COMMA, DOT, MINUS, PLUS, SEMICOLON, SLASH, STAR, 7 | 8 | // One or two character tokens. 9 | BANG, BANG_EQUAL, 10 | EQUAL, EQUAL_EQUAL, 11 | GREATER, GREATER_EQUAL, 12 | LESS, LESS_EQUAL, 13 | 14 | // Literals. 15 | IDENTIFIER, STRING, NUMBER, 16 | 17 | // Keywords. 18 | AND, CLASS, ELSE, FALSE, FUN, FOR, IF, NIL, OR, 19 | PRINT, RETURN, SUPER, THIS, TRUE, VAR, WHILE, 20 | 21 | EOF 22 | } 23 | -------------------------------------------------------------------------------- /note/answers/chapter15_virtual/1.md: -------------------------------------------------------------------------------- 1 | 2 | A helpful intermediate step is to explicitly parenthesize them so we can see 3 | the operator precedence: 4 | 5 | (1 * 2) + 3 6 | 1 + (2 * 3) 7 | (3 - 2) - 1 8 | (1 + (2 * 3)) - (4 / (-5)) 9 | 10 | From there, it's straightforward to mentally do a post-order traversal of the 11 | syntax trees: 12 | 13 | // (1 * 2) + 3 14 | CONST 1 15 | CONST 2 16 | MULTIPLY 17 | CONST 3 18 | ADD 19 | 20 | // 1 + (2 * 3) 21 | CONST 1 22 | CONST 2 23 | CONST 3 24 | MULTIPLY 25 | ADD 26 | 27 | // (3 - 2) - 1 28 | CONST 3 29 | CONST 2 30 | SUBTRACT 31 | CONST 1 32 | SUBTRACT 33 | 34 | // (1 + (2 * 3)) - (4 / (-5)) 35 | CONST 1 36 | CONST 2 37 | CONST 3 38 | MULTIPLY 39 | ADD 40 | CONST 4 41 | CONST 5 42 | NEGATE 43 | DIVIDE 44 | SUBTRACT 45 | -------------------------------------------------------------------------------- /note/answers/chapter15_virtual/2.md: -------------------------------------------------------------------------------- 1 | First, let's parenthesize: 2 | 3 | 4 - (3 * (- 2)) 4 | 5 | That gives: 6 | 7 | CONST 4 8 | CONST 3 9 | CONST 2 10 | NEGATE 11 | MULTIPLY 12 | SUBTRACT 13 | 14 | Without negation, we need to subtract a number from zero to negate it, so the 15 | code conceptually becomes: 16 | 17 | 4 - (3 * (0 - 2)) 18 | 19 | Which is: 20 | 21 | CONST 4 22 | CONST 3 23 | CONST 0 // <-- 24 | CONST 2 25 | SUBTRACT // <-- 26 | MULTIPLY 27 | SUBTRACT 28 | 29 | Without subtraction, we add the negation of the subtrahend: 30 | 31 | 4 + - (3 * (- 2)) 32 | 33 | Which is: 34 | 35 | CONST 4 36 | CONST 3 37 | CONST 2 38 | NEGATE 39 | MULTIPLY 40 | NEGATE // <-- 41 | ADD // <-- 42 | 43 | I do think it makes sense to have both instructions. The overhead of dispatching 44 | is pretty high, so you want instructions as high level as possible, you want to 45 | fill your opcode space, and you want common operations to encode as a single 46 | instruction when possible. 47 | 48 | Given how common both negation and subtraction are, and given that we've got 49 | plenty of room in our opcode set, it makes perfect sense to have instructions 50 | for both. 51 | 52 | I would also consider specialized instructions to load common number constants 53 | like zero and one. It might be worth having instructions to increment and 54 | decrement a number too. 55 | -------------------------------------------------------------------------------- /note/answers/chapter23_jumping/3.md: -------------------------------------------------------------------------------- 1 | Reusing [an old StackOverflow answer of mine][answer]: 2 | 3 | [answer]: https://stackoverflow.com/a/4296080/9457 4 | 5 | Most languages have built-in functions to cover the common cases, but 6 | "fencepost" loops are always a chore: loops where you want to do something on 7 | each iteration and also do something else between iterations. For example, 8 | joining strings with a separator: 9 | 10 | ``` 11 | String result = ""; 12 | for (int i = 0; i < items.Count; i++) { 13 | result += items[i]; 14 | if (i < items.Count - 1) result += ", "; // This is gross. 15 | // What if I can't access items by index? 16 | // I have off-by-one errors *every* time I do this. 17 | } 18 | ``` 19 | 20 | I know folds can cover this case, but sometimes you want something imperative. 21 | It would be cool if you could do: 22 | 23 | ``` 24 | String result = ""; 25 | for (var item in items) { 26 | result += item; 27 | } between { 28 | result += ", "; 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /note/answers/chapter25_closures/3.lox: -------------------------------------------------------------------------------- 1 | // Here is the classic message-based pattern: 2 | fun vector(x, y) { 3 | fun object(message) { 4 | fun add(other) { 5 | return vector(x + other("x"), y + other("y")); 6 | } 7 | 8 | if (message == "x") return x; 9 | if (message == "y") return y; 10 | if (message == "add") return add; 11 | print "unknown message"; 12 | } 13 | 14 | return object; 15 | } 16 | 17 | var a = vector(1, 2); 18 | var b = vector(3, 4); 19 | var c = a("add")(b); 20 | print c("x"); 21 | print c("y"); 22 | 23 | // The constructor, "vector()" returns a closure that closes over the object's 24 | // fields. In this case, it's the "x" and "y" parameters. The closure accepts a 25 | // single argument which is the string name of the "method" to invoke on the 26 | // object. It supports three methods: 27 | // 28 | // "x" returns the vector's X coordinate. Likewise "y". "add" returns a second 29 | // function, which is the add method. That function in turn accepts an argument 30 | // for the other vector to add to it. 31 | -------------------------------------------------------------------------------- /note/answers/chapter27_classes/4.md: -------------------------------------------------------------------------------- 1 | I'll just point you to a resource. Look for the paper "An Efficient 2 | Implementation of Self, a Dynamically-Typed Object-Oriented Language Based on 3 | Prototypes". 4 | -------------------------------------------------------------------------------- /note/answers/chapter28_methods/2.md: -------------------------------------------------------------------------------- 1 | The answer here is "inline caching". At each callsite, the VM inserts a little 2 | space to store a cached reference to a class and a method. When the callsite is 3 | first reached, the VM looks up the class of the receiver and then looks up the 4 | method on that class. It stores that class and method in the cache next to that 5 | callsite and then invokes the method as normal. 6 | 7 | The next time that callsite executes, the VM checks to see if the receiver has 8 | the same class as the cached one. If so, it knows the same method will be 9 | resolved so it uses the cached method directly instead of looking it up again. 10 | -------------------------------------------------------------------------------- /note/answers/chapter28_methods/3.md: -------------------------------------------------------------------------------- 1 | I'm actually *not* a fan of this choice, though it is certainly a common one. 2 | I like how Ruby uses a leading `@` to distinguish instance fields from methods 3 | and getters on the object. In my own language Wren, I use a leading underscore 4 | to similar effect. 5 | 6 | This means that methods and fields never shadow one another since they are 7 | textually distinct. With my language Wren, it also means that we can tell the 8 | set of fields a class uses just by parsing the class body. We can thus avoid 9 | the need for a hash table to store the instance's state. Instead, an instance 10 | has a single inline array of fields. Field access is a simple array lookup with 11 | an index determined at compile time. It is *much* faster than Lox. 12 | 13 | But, for the book, I felt it made sense to stick with a more traditional 14 | language choice. JavaScript, Python, Lua, and many other dynamically typed 15 | languages all treat objects as hash tables under the hood, so I felt it was 16 | worth showing how those languages work. 17 | -------------------------------------------------------------------------------- /note/answers/chapter29_superclasses/1.md: -------------------------------------------------------------------------------- 1 | I created a hobby language named Wren. The clox VM was actually based on Wren's 2 | implementation, and the design of Lox borrows a lot from Wren. Lox is sort of 3 | simplified slightly-less-weird Wren. 4 | 5 | In Wren, fields have a leading underscore in their name. This solves the problem 6 | in the previous chapter of fields shadowing methods, and it also helps address 7 | this problem. Because the compiler can syntactically identify a field access, 8 | and it knows the surrounding class, it effectively "renames" each field based 9 | on the surrounding class. 10 | 11 | So in a program like this (using more Lox-like syntax): 12 | 13 | ``` 14 | class A { 15 | init() { 16 | _field = "a field"; 17 | } 18 | } 19 | 20 | class B < A { 21 | init() { 22 | super.init(); 23 | _field = "b field"; 24 | } 25 | } 26 | ``` 27 | 28 | There is no collision here because the compiler treats `_field` inside methods 29 | of class A as having a distinct name from `_field` inside class B. The main 30 | downside is that fields become "private" instead of "protected". There's no way 31 | for a subclass to directly access a field defined by a superclass, even on the 32 | same instance. 33 | 34 | I think that's a worthwhile trade-off. 35 | -------------------------------------------------------------------------------- /note/research.txt: -------------------------------------------------------------------------------- 1 | http://en.wikipedia.org/wiki/PL/0 2 | 3 | "Structure and Interpretation of Efficient Interpreters" (in dropbox) 4 | 5 | http://blog.analogmachine.org/2011/09/20/lets-build-a-compiler/ 6 | 7 | "Compiler Construction" by Wirth -------------------------------------------------------------------------------- /note/struct sizes.txt: -------------------------------------------------------------------------------- 1 | typedef struct Obj2 { 2 | ObjType type; 3 | } Obj2; 4 | 5 | typedef struct ObjString2 { 6 | Obj2 obj; 7 | int length; 8 | char* chars; 9 | 10 | } ObjString2; 11 | 12 | int main(int argc, const char* argv[]) { 13 | printf("sizeof(Obj) %ld\n", sizeof(Obj2)); 14 | printf("sizeof(ObjType) %ld\n", sizeof(ObjType)); 15 | printf("offset(Obj, type) %ld\n", offsetof(Obj2, type)); 16 | printf("sizeof(ObjString) %ld\n", sizeof(ObjString2)); 17 | printf("offset(ObjString, obj) %ld\n", offsetof(ObjString2, obj)); 18 | printf("offset(ObjString, length) %ld\n", offsetof(ObjString2, length)); 19 | printf("offset(ObjString, chars) %ld\n", offsetof(ObjString2, chars)); 20 | printf("sizeof(Value) %ld\n", sizeof(Value)); 21 | printf("sizeof(ValueType) %ld\n", sizeof(ValueType)); 22 | printf("offset(Value, ValueType) %ld\n", offsetof(Value, type)); 23 | printf("offset(Value, as) %ld\n", offsetof(Value, as)); 24 | printf("sizeof(Obj*) %ld\n", sizeof(Obj*)); 25 | } 26 | 27 | sizeof(Obj) 4 28 | sizeof(ObjType) 4 29 | offset(Obj, type) 0 30 | sizeof(ObjString) 16 31 | offset(ObjString, obj) 0 32 | offset(ObjString, length) 4 33 | offset(ObjString, chars) 8 34 | sizeof(Value) 16 35 | sizeof(ValueType) 4 36 | offset(Value, ValueType) 0 37 | offset(Value, as) 8 38 | sizeof(Obj*) 8 -------------------------------------------------------------------------------- /note/todo.txt: -------------------------------------------------------------------------------- 1 | Print: 2 | 3 | - Order proof from IngramSpark. 4 | 5 | eBook: 6 | 7 | - Fix all TODOs in asset/ebook/*. 8 | - Create wider cover image for non-Kindle. 9 | - Style TOC page. 10 | - Assign ISBN numbers: 11 | https://www.myidentifiers.com/title_registration?isbn=978-0-9905829-3-9&icon_type=New 12 | - Get example snippet in chapter one looking right. 13 | - Make eBook exporter handle Kindle. 14 | - Generate PDF version. 15 | - Include cover. 16 | - Get table of contents links working. 17 | - Style tables (see "Chunks of Bytecode"). 18 | - Check out on a few different readers. 19 | - Go through whole book and see how it looks. 20 | - Make sure inline images look OK. 21 | 22 | Web: 23 | 24 | - Link to stores. 25 | - Export sample chapter PDF. 26 | - Remove "not done" script, templates and styles. 27 | - Replace "work in progress" header with something about print edition. 28 | - Add snippets for remaining chapters to compile_snippets to pin down which 29 | snippets reach a working point. 30 | -------------------------------------------------------------------------------- /site/.htaccess: -------------------------------------------------------------------------------- 1 | ErrorDocument 404 /404.html 2 | 3 | Redirect /beta http://journal.stuffwithstuff.com/2012/12/19/the-impoliteness-of-overriding-methods/ 4 | Redirect /budget https://steveklabnik.com/writing/the-language-strangeness-budget 5 | Redirect /dragon https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools 6 | Redirect /finch http://finch.stuffwithstuff.com/ 7 | Redirect /koan http://wiki.c2.com/?ClosuresAndObjectsAreEquivalent 8 | Redirect /locality http://gameprogrammingpatterns.com/data-locality.html 9 | Redirect /lua5 https://www.lua.org/doc/jucs05.pdf 10 | Redirect /ports https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations 11 | Redirect /pratt http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ 12 | Redirect /prototypes http://gameprogrammingpatterns.com/prototype.html 13 | Redirect /repo https://github.com/munificent/craftinginterpreters 14 | Redirect /singleton http://gameprogrammingpatterns.com/singleton.html 15 | Redirect /state http://gameprogrammingpatterns.com/state.html 16 | Redirect /tests https://github.com/munificent/craftinginterpreters/tree/master/test 17 | Redirect /wizard https://mitpress.mit.edu/sites/default/files/sicp/index.html 18 | Redirect /wren https://wren.io/ 19 | -------------------------------------------------------------------------------- /site/columns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/columns.png -------------------------------------------------------------------------------- /site/font/crimson-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/font/crimson-bold.woff -------------------------------------------------------------------------------- /site/font/crimson-bolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/font/crimson-bolditalic.woff -------------------------------------------------------------------------------- /site/font/crimson-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/font/crimson-italic.woff -------------------------------------------------------------------------------- /site/font/crimson-roman.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/font/crimson-roman.woff -------------------------------------------------------------------------------- /site/font/crimson-semibold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/font/crimson-semibold.woff -------------------------------------------------------------------------------- /site/font/crimson-semibolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/font/crimson-semibolditalic.woff -------------------------------------------------------------------------------- /site/image/a-map-of-the-territory/ast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-map-of-the-territory/ast.png -------------------------------------------------------------------------------- /site/image/a-map-of-the-territory/mountain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-map-of-the-territory/mountain.png -------------------------------------------------------------------------------- /site/image/a-map-of-the-territory/plants.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-map-of-the-territory/plants.png -------------------------------------------------------------------------------- /site/image/a-map-of-the-territory/string.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-map-of-the-territory/string.png -------------------------------------------------------------------------------- /site/image/a-map-of-the-territory/tokens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-map-of-the-territory/tokens.png -------------------------------------------------------------------------------- /site/image/a-map-of-the-territory/venn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-map-of-the-territory/venn.png -------------------------------------------------------------------------------- /site/image/a-virtual-machine/array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-virtual-machine/array.png -------------------------------------------------------------------------------- /site/image/a-virtual-machine/ast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-virtual-machine/ast.png -------------------------------------------------------------------------------- /site/image/a-virtual-machine/bars-stacked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-virtual-machine/bars-stacked.png -------------------------------------------------------------------------------- /site/image/a-virtual-machine/bars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-virtual-machine/bars.png -------------------------------------------------------------------------------- /site/image/a-virtual-machine/chunk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-virtual-machine/chunk.png -------------------------------------------------------------------------------- /site/image/a-virtual-machine/pancakes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-virtual-machine/pancakes.png -------------------------------------------------------------------------------- /site/image/a-virtual-machine/reverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-virtual-machine/reverse.png -------------------------------------------------------------------------------- /site/image/a-virtual-machine/stack-c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-virtual-machine/stack-c.png -------------------------------------------------------------------------------- /site/image/a-virtual-machine/stack-crepe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-virtual-machine/stack-crepe.png -------------------------------------------------------------------------------- /site/image/a-virtual-machine/stack-empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/a-virtual-machine/stack-empty.png -------------------------------------------------------------------------------- /site/image/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/background.png -------------------------------------------------------------------------------- /site/image/calls-and-functions/argument-stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/calls-and-functions/argument-stack.png -------------------------------------------------------------------------------- /site/image/calls-and-functions/arithmetic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/calls-and-functions/arithmetic.png -------------------------------------------------------------------------------- /site/image/calls-and-functions/calls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/calls-and-functions/calls.png -------------------------------------------------------------------------------- /site/image/calls-and-functions/overlapping-windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/calls-and-functions/overlapping-windows.png -------------------------------------------------------------------------------- /site/image/calls-and-functions/parameter-window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/calls-and-functions/parameter-window.png -------------------------------------------------------------------------------- /site/image/calls-and-functions/return.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/calls-and-functions/return.png -------------------------------------------------------------------------------- /site/image/calls-and-functions/window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/calls-and-functions/window.png -------------------------------------------------------------------------------- /site/image/chunks-of-bytecode/ast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/chunks-of-bytecode/ast.png -------------------------------------------------------------------------------- /site/image/chunks-of-bytecode/format.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/chunks-of-bytecode/format.png -------------------------------------------------------------------------------- /site/image/chunks-of-bytecode/grow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/chunks-of-bytecode/grow.png -------------------------------------------------------------------------------- /site/image/chunks-of-bytecode/insert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/chunks-of-bytecode/insert.png -------------------------------------------------------------------------------- /site/image/chunks-of-bytecode/phases.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/chunks-of-bytecode/phases.png -------------------------------------------------------------------------------- /site/image/classes-and-instances/klass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/classes-and-instances/klass.png -------------------------------------------------------------------------------- /site/image/classes-and-instances/lox-clox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/classes-and-instances/lox-clox.png -------------------------------------------------------------------------------- /site/image/classes-and-instances/stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/classes-and-instances/stack.png -------------------------------------------------------------------------------- /site/image/classes/bound-method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/classes/bound-method.png -------------------------------------------------------------------------------- /site/image/classes/call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/classes/call.png -------------------------------------------------------------------------------- /site/image/classes/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/classes/circle.png -------------------------------------------------------------------------------- /site/image/classes/closure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/classes/closure.png -------------------------------------------------------------------------------- /site/image/classes/method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/classes/method.png -------------------------------------------------------------------------------- /site/image/classes/setter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/classes/setter.png -------------------------------------------------------------------------------- /site/image/classes/zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/classes/zip.png -------------------------------------------------------------------------------- /site/image/closures/closing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/closures/closing.png -------------------------------------------------------------------------------- /site/image/closures/execution-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/closures/execution-flow.png -------------------------------------------------------------------------------- /site/image/closures/flying.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/closures/flying.png -------------------------------------------------------------------------------- /site/image/closures/linked-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/closures/linked-list.png -------------------------------------------------------------------------------- /site/image/closures/linked-upvalues.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/closures/linked-upvalues.png -------------------------------------------------------------------------------- /site/image/closures/obj-closure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/closures/obj-closure.png -------------------------------------------------------------------------------- /site/image/closures/open-upvalue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/closures/open-upvalue.png -------------------------------------------------------------------------------- /site/image/closures/recursion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/closures/recursion.png -------------------------------------------------------------------------------- /site/image/compiling-expressions/calls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/compiling-expressions/calls.png -------------------------------------------------------------------------------- /site/image/compiling-expressions/connections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/compiling-expressions/connections.png -------------------------------------------------------------------------------- /site/image/compiling-expressions/keyhole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/compiling-expressions/keyhole.png -------------------------------------------------------------------------------- /site/image/compiling-expressions/mystery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/compiling-expressions/mystery.png -------------------------------------------------------------------------------- /site/image/compiling-expressions/pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/compiling-expressions/pipeline.png -------------------------------------------------------------------------------- /site/image/compiling-expressions/points-to.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/compiling-expressions/points-to.png -------------------------------------------------------------------------------- /site/image/control-flow/dangling-else.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/control-flow/dangling-else.png -------------------------------------------------------------------------------- /site/image/control-flow/sugar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/control-flow/sugar.png -------------------------------------------------------------------------------- /site/image/control-flow/turing-machine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/control-flow/turing-machine.png -------------------------------------------------------------------------------- /site/image/dogshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/dogshot.jpg -------------------------------------------------------------------------------- /site/image/evaluating-expressions/lightning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/evaluating-expressions/lightning.png -------------------------------------------------------------------------------- /site/image/evaluating-expressions/muffin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/evaluating-expressions/muffin.png -------------------------------------------------------------------------------- /site/image/evaluating-expressions/skeleton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/evaluating-expressions/skeleton.png -------------------------------------------------------------------------------- /site/image/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/favicon.png -------------------------------------------------------------------------------- /site/image/format-ebook.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/format-ebook.jpg -------------------------------------------------------------------------------- /site/image/format-pdf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/format-pdf.jpg -------------------------------------------------------------------------------- /site/image/format-print.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/format-print.jpg -------------------------------------------------------------------------------- /site/image/format-web.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/format-web.jpg -------------------------------------------------------------------------------- /site/image/functions/binding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/functions/binding.png -------------------------------------------------------------------------------- /site/image/functions/body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/functions/body.png -------------------------------------------------------------------------------- /site/image/functions/closure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/functions/closure.png -------------------------------------------------------------------------------- /site/image/functions/foreign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/functions/foreign.png -------------------------------------------------------------------------------- /site/image/functions/global.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/functions/global.png -------------------------------------------------------------------------------- /site/image/functions/lambda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/functions/lambda.png -------------------------------------------------------------------------------- /site/image/functions/recursion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/functions/recursion.png -------------------------------------------------------------------------------- /site/image/garbage-collection/baguette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/garbage-collection/baguette.png -------------------------------------------------------------------------------- /site/image/garbage-collection/black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/garbage-collection/black.png -------------------------------------------------------------------------------- /site/image/garbage-collection/gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/garbage-collection/gray.png -------------------------------------------------------------------------------- /site/image/garbage-collection/latency-throughput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/garbage-collection/latency-throughput.png -------------------------------------------------------------------------------- /site/image/garbage-collection/mark-sweep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/garbage-collection/mark-sweep.png -------------------------------------------------------------------------------- /site/image/garbage-collection/reachable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/garbage-collection/reachable.png -------------------------------------------------------------------------------- /site/image/garbage-collection/recycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/garbage-collection/recycle.png -------------------------------------------------------------------------------- /site/image/garbage-collection/stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/garbage-collection/stack.png -------------------------------------------------------------------------------- /site/image/garbage-collection/tricolor-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/garbage-collection/tricolor-trace.png -------------------------------------------------------------------------------- /site/image/garbage-collection/unlink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/garbage-collection/unlink.png -------------------------------------------------------------------------------- /site/image/garbage-collection/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/garbage-collection/white.png -------------------------------------------------------------------------------- /site/image/ginny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/ginny.png -------------------------------------------------------------------------------- /site/image/global-variables/ast-bad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/global-variables/ast-bad.png -------------------------------------------------------------------------------- /site/image/global-variables/ast-good.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/global-variables/ast-good.png -------------------------------------------------------------------------------- /site/image/global-variables/setter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/global-variables/setter.png -------------------------------------------------------------------------------- /site/image/global-variables/stack-effect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/global-variables/stack-effect.png -------------------------------------------------------------------------------- /site/image/hash-tables/bucket-array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/bucket-array.png -------------------------------------------------------------------------------- /site/image/hash-tables/chaining.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/chaining.png -------------------------------------------------------------------------------- /site/image/hash-tables/collision.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/collision.png -------------------------------------------------------------------------------- /site/image/hash-tables/delete-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/delete-1.png -------------------------------------------------------------------------------- /site/image/hash-tables/delete-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/delete-2.png -------------------------------------------------------------------------------- /site/image/hash-tables/delete-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/delete-3.png -------------------------------------------------------------------------------- /site/image/hash-tables/insert-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/insert-1.png -------------------------------------------------------------------------------- /site/image/hash-tables/insert-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/insert-2.png -------------------------------------------------------------------------------- /site/image/hash-tables/insert-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/insert-3.png -------------------------------------------------------------------------------- /site/image/hash-tables/insert-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/insert-4.png -------------------------------------------------------------------------------- /site/image/hash-tables/insert-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/insert-5.png -------------------------------------------------------------------------------- /site/image/hash-tables/insert-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/insert-6.png -------------------------------------------------------------------------------- /site/image/hash-tables/insert-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/insert-7.png -------------------------------------------------------------------------------- /site/image/hash-tables/pigeons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/pigeons.png -------------------------------------------------------------------------------- /site/image/hash-tables/tombstone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/hash-tables/tombstone.png -------------------------------------------------------------------------------- /site/image/header-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/header-small.png -------------------------------------------------------------------------------- /site/image/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/header.png -------------------------------------------------------------------------------- /site/image/inheritance/classes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/inheritance/classes.png -------------------------------------------------------------------------------- /site/image/inheritance/doughnuts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/inheritance/doughnuts.png -------------------------------------------------------------------------------- /site/image/inheritance/environments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/inheritance/environments.png -------------------------------------------------------------------------------- /site/image/inheritance/superclass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/inheritance/superclass.png -------------------------------------------------------------------------------- /site/image/inheritance/superhero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/inheritance/superhero.png -------------------------------------------------------------------------------- /site/image/introduction/bootstrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/introduction/bootstrap.png -------------------------------------------------------------------------------- /site/image/introduction/little-languages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/introduction/little-languages.png -------------------------------------------------------------------------------- /site/image/introduction/yak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/introduction/yak.png -------------------------------------------------------------------------------- /site/image/jumping-back-and-forth/and.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/jumping-back-and-forth/and.png -------------------------------------------------------------------------------- /site/image/jumping-back-and-forth/bad-else.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/jumping-back-and-forth/bad-else.png -------------------------------------------------------------------------------- /site/image/jumping-back-and-forth/for.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/jumping-back-and-forth/for.png -------------------------------------------------------------------------------- /site/image/jumping-back-and-forth/full-if-else.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/jumping-back-and-forth/full-if-else.png -------------------------------------------------------------------------------- /site/image/jumping-back-and-forth/if-else.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/jumping-back-and-forth/if-else.png -------------------------------------------------------------------------------- /site/image/jumping-back-and-forth/if-without-else.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/jumping-back-and-forth/if-without-else.png -------------------------------------------------------------------------------- /site/image/jumping-back-and-forth/or.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/jumping-back-and-forth/or.png -------------------------------------------------------------------------------- /site/image/jumping-back-and-forth/patch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/jumping-back-and-forth/patch.png -------------------------------------------------------------------------------- /site/image/jumping-back-and-forth/while.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/jumping-back-and-forth/while.png -------------------------------------------------------------------------------- /site/image/local-variables/block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/local-variables/block.png -------------------------------------------------------------------------------- /site/image/local-variables/declaration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/local-variables/declaration.png -------------------------------------------------------------------------------- /site/image/local-variables/local-slots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/local-variables/local-slots.png -------------------------------------------------------------------------------- /site/image/local-variables/phases.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/local-variables/phases.png -------------------------------------------------------------------------------- /site/image/local-variables/scopes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/local-variables/scopes.png -------------------------------------------------------------------------------- /site/image/logotype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/logotype.png -------------------------------------------------------------------------------- /site/image/methods-and-initializers/benchmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/methods-and-initializers/benchmark.png -------------------------------------------------------------------------------- /site/image/methods-and-initializers/bind-method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/methods-and-initializers/bind-method.png -------------------------------------------------------------------------------- /site/image/methods-and-initializers/closure-slot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/methods-and-initializers/closure-slot.png -------------------------------------------------------------------------------- /site/image/methods-and-initializers/init-call-frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/methods-and-initializers/init-call-frame.png -------------------------------------------------------------------------------- /site/image/methods-and-initializers/method-instructions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/methods-and-initializers/method-instructions.png -------------------------------------------------------------------------------- /site/image/methods-and-initializers/party-hat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/methods-and-initializers/party-hat.png -------------------------------------------------------------------------------- /site/image/optimization/bools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/optimization/bools.png -------------------------------------------------------------------------------- /site/image/optimization/double.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/optimization/double.png -------------------------------------------------------------------------------- /site/image/optimization/hash-chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/optimization/hash-chart.png -------------------------------------------------------------------------------- /site/image/optimization/mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/optimization/mask.png -------------------------------------------------------------------------------- /site/image/optimization/nan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/optimization/nan.png -------------------------------------------------------------------------------- /site/image/optimization/nil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/optimization/nil.png -------------------------------------------------------------------------------- /site/image/optimization/obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/optimization/obj.png -------------------------------------------------------------------------------- /site/image/optimization/qnan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/optimization/qnan.png -------------------------------------------------------------------------------- /site/image/optimization/union.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/optimization/union.png -------------------------------------------------------------------------------- /site/image/parsing-expressions/direction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/parsing-expressions/direction.png -------------------------------------------------------------------------------- /site/image/parsing-expressions/panic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/parsing-expressions/panic.png -------------------------------------------------------------------------------- /site/image/parsing-expressions/sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/parsing-expressions/sequence.png -------------------------------------------------------------------------------- /site/image/parsing-expressions/syntax-trees.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/parsing-expressions/syntax-trees.png -------------------------------------------------------------------------------- /site/image/parsing-expressions/tokens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/parsing-expressions/tokens.png -------------------------------------------------------------------------------- /site/image/representing-code/breakfast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/representing-code/breakfast.png -------------------------------------------------------------------------------- /site/image/representing-code/columns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/representing-code/columns.png -------------------------------------------------------------------------------- /site/image/representing-code/expression.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/representing-code/expression.png -------------------------------------------------------------------------------- /site/image/representing-code/rows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/representing-code/rows.png -------------------------------------------------------------------------------- /site/image/representing-code/table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/representing-code/table.png -------------------------------------------------------------------------------- /site/image/representing-code/tree-evaluate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/representing-code/tree-evaluate.png -------------------------------------------------------------------------------- /site/image/representing-code/visitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/representing-code/visitor.png -------------------------------------------------------------------------------- /site/image/resolving-and-binding/environment-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/resolving-and-binding/environment-1.png -------------------------------------------------------------------------------- /site/image/resolving-and-binding/environment-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/resolving-and-binding/environment-2.png -------------------------------------------------------------------------------- /site/image/resolving-and-binding/environment-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/resolving-and-binding/environment-3.png -------------------------------------------------------------------------------- /site/image/resolving-and-binding/environment-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/resolving-and-binding/environment-4.png -------------------------------------------------------------------------------- /site/image/resolving-and-binding/environment-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/resolving-and-binding/environment-5.png -------------------------------------------------------------------------------- /site/image/resolving-and-binding/split.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/resolving-and-binding/split.png -------------------------------------------------------------------------------- /site/image/scanning-on-demand/axolotl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/scanning-on-demand/axolotl.png -------------------------------------------------------------------------------- /site/image/scanning-on-demand/fields.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/scanning-on-demand/fields.png -------------------------------------------------------------------------------- /site/image/scanning-on-demand/keywords.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/scanning-on-demand/keywords.png -------------------------------------------------------------------------------- /site/image/scanning-on-demand/numbers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/scanning-on-demand/numbers.png -------------------------------------------------------------------------------- /site/image/scanning-on-demand/pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/scanning-on-demand/pipeline.png -------------------------------------------------------------------------------- /site/image/scanning/lexemes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/scanning/lexemes.png -------------------------------------------------------------------------------- /site/image/scanning/lexigator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/scanning/lexigator.png -------------------------------------------------------------------------------- /site/image/statements-and-state/blocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/statements-and-state/blocks.png -------------------------------------------------------------------------------- /site/image/statements-and-state/brain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/statements-and-state/brain.png -------------------------------------------------------------------------------- /site/image/statements-and-state/cactus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/statements-and-state/cactus.png -------------------------------------------------------------------------------- /site/image/statements-and-state/chaining.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/statements-and-state/chaining.png -------------------------------------------------------------------------------- /site/image/statements-and-state/environment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/statements-and-state/environment.png -------------------------------------------------------------------------------- /site/image/strings/obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/strings/obj.png -------------------------------------------------------------------------------- /site/image/strings/pstring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/strings/pstring.png -------------------------------------------------------------------------------- /site/image/strings/stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/strings/stack.png -------------------------------------------------------------------------------- /site/image/strings/value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/strings/value.png -------------------------------------------------------------------------------- /site/image/strings/viola.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/strings/viola.png -------------------------------------------------------------------------------- /site/image/superclasses/clox-resolve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/superclasses/clox-resolve.png -------------------------------------------------------------------------------- /site/image/superclasses/inherit-stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/superclasses/inherit-stack.png -------------------------------------------------------------------------------- /site/image/superclasses/jlox-resolve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/superclasses/jlox-resolve.png -------------------------------------------------------------------------------- /site/image/superclasses/monkey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/superclasses/monkey.png -------------------------------------------------------------------------------- /site/image/superclasses/super-instructions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/superclasses/super-instructions.png -------------------------------------------------------------------------------- /site/image/superclasses/super-invoke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/superclasses/super-invoke.png -------------------------------------------------------------------------------- /site/image/the-lox-language/class-lookup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/the-lox-language/class-lookup.png -------------------------------------------------------------------------------- /site/image/the-lox-language/prototype-lookup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/the-lox-language/prototype-lookup.png -------------------------------------------------------------------------------- /site/image/types-of-values/memcmp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/types-of-values/memcmp.png -------------------------------------------------------------------------------- /site/image/types-of-values/struct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/types-of-values/struct.png -------------------------------------------------------------------------------- /site/image/types-of-values/union.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/types-of-values/union.png -------------------------------------------------------------------------------- /site/image/types-of-values/universe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/types-of-values/universe.png -------------------------------------------------------------------------------- /site/image/types-of-values/value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/types-of-values/value.png -------------------------------------------------------------------------------- /site/image/wood.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/image/wood.jpg -------------------------------------------------------------------------------- /site/index.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["../asset/sass/shared.scss","../asset/sass/sign-up.scss","../asset/index.scss"],"names":[],"mappings":"AAkCA;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAKF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAKF;EACE;EACA;;;AChGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EAEA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;;ACzEJ;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE,SFSI;EERJ;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE,OF5Cc;EE6Cd;EACA;EAEA;;;AAIF;EACE,OFrDc;;;AEwDhB;EACE,OFxDc;EEyDd;;;AAGF;EACE;EACA;EACA;EACA;EACA,YFlEc;EEmEd;EACA;EACA;EAEA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE,OFvEW;EEwEX;EACA;;;AAIF;EACE;IACE;;;EAGF;IACE;;;AAMJ;EACE;IACE;IACA;;;EAGF;IACE;IACA;IACA;;;EAGF;IACE;;;EAGF;IACE;IACA;IACA","file":"index.css"} -------------------------------------------------------------------------------- /site/rows-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/rows-22.png -------------------------------------------------------------------------------- /site/rows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/rows.png -------------------------------------------------------------------------------- /site/sample.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/site/sample.pdf -------------------------------------------------------------------------------- /test/assignment/associativity.lox: -------------------------------------------------------------------------------- 1 | var a = "a"; 2 | var b = "b"; 3 | var c = "c"; 4 | 5 | // Assignment is right-associative. 6 | a = b = c; 7 | print a; // expect: c 8 | print b; // expect: c 9 | print c; // expect: c 10 | -------------------------------------------------------------------------------- /test/assignment/global.lox: -------------------------------------------------------------------------------- 1 | var a = "before"; 2 | print a; // expect: before 3 | 4 | a = "after"; 5 | print a; // expect: after 6 | 7 | print a = "arg"; // expect: arg 8 | print a; // expect: arg 9 | -------------------------------------------------------------------------------- /test/assignment/grouping.lox: -------------------------------------------------------------------------------- 1 | var a = "a"; 2 | (a) = "value"; // Error at '=': Invalid assignment target. 3 | -------------------------------------------------------------------------------- /test/assignment/infix_operator.lox: -------------------------------------------------------------------------------- 1 | var a = "a"; 2 | var b = "b"; 3 | a + b = "value"; // Error at '=': Invalid assignment target. 4 | -------------------------------------------------------------------------------- /test/assignment/local.lox: -------------------------------------------------------------------------------- 1 | { 2 | var a = "before"; 3 | print a; // expect: before 4 | 5 | a = "after"; 6 | print a; // expect: after 7 | 8 | print a = "arg"; // expect: arg 9 | print a; // expect: arg 10 | } 11 | -------------------------------------------------------------------------------- /test/assignment/prefix_operator.lox: -------------------------------------------------------------------------------- 1 | var a = "a"; 2 | !a = "value"; // Error at '=': Invalid assignment target. 3 | -------------------------------------------------------------------------------- /test/assignment/syntax.lox: -------------------------------------------------------------------------------- 1 | // Assignment on RHS of variable. 2 | var a = "before"; 3 | var c = a = "var"; 4 | print a; // expect: var 5 | print c; // expect: var 6 | -------------------------------------------------------------------------------- /test/assignment/to_this.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | Foo() { 3 | this = "value"; // Error at '=': Invalid assignment target. 4 | } 5 | } 6 | 7 | Foo(); 8 | -------------------------------------------------------------------------------- /test/assignment/undefined.lox: -------------------------------------------------------------------------------- 1 | unknown = "what"; // expect runtime error: Undefined variable 'unknown'. 2 | -------------------------------------------------------------------------------- /test/benchmark/equality.lox: -------------------------------------------------------------------------------- 1 | var i = 0; 2 | 3 | var loopStart = clock(); 4 | 5 | while (i < 10000000) { 6 | i = i + 1; 7 | 8 | 1; 1; 1; 2; 1; nil; 1; "str"; 1; true; 9 | nil; nil; nil; 1; nil; "str"; nil; true; 10 | true; true; true; 1; true; false; true; "str"; true; nil; 11 | "str"; "str"; "str"; "stru"; "str"; 1; "str"; nil; "str"; true; 12 | } 13 | 14 | var loopTime = clock() - loopStart; 15 | 16 | var start = clock(); 17 | 18 | i = 0; 19 | while (i < 10000000) { 20 | i = i + 1; 21 | 22 | 1 == 1; 1 == 2; 1 == nil; 1 == "str"; 1 == true; 23 | nil == nil; nil == 1; nil == "str"; nil == true; 24 | true == true; true == 1; true == false; true == "str"; true == nil; 25 | "str" == "str"; "str" == "stru"; "str" == 1; "str" == nil; "str" == true; 26 | } 27 | 28 | var elapsed = clock() - start; 29 | print "loop"; 30 | print loopTime; 31 | print "elapsed"; 32 | print elapsed; 33 | print "equals"; 34 | print elapsed - loopTime; 35 | -------------------------------------------------------------------------------- /test/benchmark/fib.lox: -------------------------------------------------------------------------------- 1 | fun fib(n) { 2 | if (n < 2) return n; 3 | return fib(n - 2) + fib(n - 1); 4 | } 5 | 6 | var start = clock(); 7 | print fib(35) == 9227465; 8 | print clock() - start; 9 | -------------------------------------------------------------------------------- /test/benchmark/instantiation.lox: -------------------------------------------------------------------------------- 1 | // This benchmark stresses instance creation and initializer calling. 2 | 3 | class Foo { 4 | init() {} 5 | } 6 | 7 | var start = clock(); 8 | var i = 0; 9 | while (i < 500000) { 10 | Foo(); 11 | Foo(); 12 | Foo(); 13 | Foo(); 14 | Foo(); 15 | Foo(); 16 | Foo(); 17 | Foo(); 18 | Foo(); 19 | Foo(); 20 | Foo(); 21 | Foo(); 22 | Foo(); 23 | Foo(); 24 | Foo(); 25 | Foo(); 26 | Foo(); 27 | Foo(); 28 | Foo(); 29 | Foo(); 30 | Foo(); 31 | Foo(); 32 | Foo(); 33 | Foo(); 34 | Foo(); 35 | Foo(); 36 | Foo(); 37 | Foo(); 38 | Foo(); 39 | Foo(); 40 | i = i + 1; 41 | } 42 | 43 | print clock() - start; 44 | -------------------------------------------------------------------------------- /test/benchmark/trees.lox: -------------------------------------------------------------------------------- 1 | class Tree { 2 | init(depth) { 3 | this.depth = depth; 4 | if (depth > 0) { 5 | this.a = Tree(depth - 1); 6 | this.b = Tree(depth - 1); 7 | this.c = Tree(depth - 1); 8 | this.d = Tree(depth - 1); 9 | this.e = Tree(depth - 1); 10 | } 11 | } 12 | 13 | walk() { 14 | if (this.depth == 0) return 0; 15 | return this.depth 16 | + this.a.walk() 17 | + this.b.walk() 18 | + this.c.walk() 19 | + this.d.walk() 20 | + this.e.walk(); 21 | } 22 | } 23 | 24 | var tree = Tree(8); 25 | var start = clock(); 26 | for (var i = 0; i < 100; i = i + 1) { 27 | if (tree.walk() != 122068) print "Error"; 28 | } 29 | print clock() - start; 30 | -------------------------------------------------------------------------------- /test/benchmark/zoo.lox: -------------------------------------------------------------------------------- 1 | class Zoo { 2 | init() { 3 | this.aarvark = 1; 4 | this.baboon = 1; 5 | this.cat = 1; 6 | this.donkey = 1; 7 | this.elephant = 1; 8 | this.fox = 1; 9 | } 10 | ant() { return this.aarvark; } 11 | banana() { return this.baboon; } 12 | tuna() { return this.cat; } 13 | hay() { return this.donkey; } 14 | grass() { return this.elephant; } 15 | mouse() { return this.fox; } 16 | } 17 | 18 | var zoo = Zoo(); 19 | var sum = 0; 20 | var start = clock(); 21 | while (sum < 10000000) { 22 | sum = sum + zoo.ant() 23 | + zoo.banana() 24 | + zoo.tuna() 25 | + zoo.hay() 26 | + zoo.grass() 27 | + zoo.mouse(); 28 | } 29 | 30 | print sum; 31 | print clock() - start; 32 | -------------------------------------------------------------------------------- /test/benchmark/zoo_batch.lox: -------------------------------------------------------------------------------- 1 | class Zoo { 2 | init() { 3 | this.aarvark = 1; 4 | this.baboon = 1; 5 | this.cat = 1; 6 | this.donkey = 1; 7 | this.elephant = 1; 8 | this.fox = 1; 9 | } 10 | ant() { return this.aarvark; } 11 | banana() { return this.baboon; } 12 | tuna() { return this.cat; } 13 | hay() { return this.donkey; } 14 | grass() { return this.elephant; } 15 | mouse() { return this.fox; } 16 | } 17 | 18 | var zoo = Zoo(); 19 | var sum = 0; 20 | var start = clock(); 21 | var batch = 0; 22 | while (clock() - start < 10) { 23 | for (var i = 0; i < 10000; i = i + 1) { 24 | sum = sum + zoo.ant() 25 | + zoo.banana() 26 | + zoo.tuna() 27 | + zoo.hay() 28 | + zoo.grass() 29 | + zoo.mouse(); 30 | } 31 | batch = batch + 1; 32 | } 33 | 34 | print sum; 35 | print batch; 36 | print clock() - start; 37 | -------------------------------------------------------------------------------- /test/block/empty.lox: -------------------------------------------------------------------------------- 1 | {} // By itself. 2 | 3 | // In a statement. 4 | if (true) {} 5 | if (false) {} else {} 6 | 7 | print "ok"; // expect: ok 8 | -------------------------------------------------------------------------------- /test/block/scope.lox: -------------------------------------------------------------------------------- 1 | var a = "outer"; 2 | 3 | { 4 | var a = "inner"; 5 | print a; // expect: inner 6 | } 7 | 8 | print a; // expect: outer 9 | -------------------------------------------------------------------------------- /test/bool/equality.lox: -------------------------------------------------------------------------------- 1 | print true == true; // expect: true 2 | print true == false; // expect: false 3 | print false == true; // expect: false 4 | print false == false; // expect: true 5 | 6 | // Not equal to other types. 7 | print true == 1; // expect: false 8 | print false == 0; // expect: false 9 | print true == "true"; // expect: false 10 | print false == "false"; // expect: false 11 | print false == ""; // expect: false 12 | 13 | print true != true; // expect: false 14 | print true != false; // expect: true 15 | print false != true; // expect: true 16 | print false != false; // expect: false 17 | 18 | // Not equal to other types. 19 | print true != 1; // expect: true 20 | print false != 0; // expect: true 21 | print true != "true"; // expect: true 22 | print false != "false"; // expect: true 23 | print false != ""; // expect: true 24 | -------------------------------------------------------------------------------- /test/bool/not.lox: -------------------------------------------------------------------------------- 1 | print !true; // expect: false 2 | print !false; // expect: true 3 | print !!true; // expect: true 4 | -------------------------------------------------------------------------------- /test/call/bool.lox: -------------------------------------------------------------------------------- 1 | true(); // expect runtime error: Can only call functions and classes. 2 | -------------------------------------------------------------------------------- /test/call/nil.lox: -------------------------------------------------------------------------------- 1 | nil(); // expect runtime error: Can only call functions and classes. 2 | -------------------------------------------------------------------------------- /test/call/num.lox: -------------------------------------------------------------------------------- 1 | 123(); // expect runtime error: Can only call functions and classes. 2 | -------------------------------------------------------------------------------- /test/call/object.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | var foo = Foo(); 4 | foo(); // expect runtime error: Can only call functions and classes. 5 | -------------------------------------------------------------------------------- /test/call/string.lox: -------------------------------------------------------------------------------- 1 | "str"(); // expect runtime error: Can only call functions and classes. 2 | -------------------------------------------------------------------------------- /test/class/empty.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | print Foo; // expect: Foo 4 | -------------------------------------------------------------------------------- /test/class/inherit_self.lox: -------------------------------------------------------------------------------- 1 | class Foo < Foo {} // Error at 'Foo': A class can't inherit from itself. 2 | -------------------------------------------------------------------------------- /test/class/inherited_method.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | inFoo() { 3 | print "in foo"; 4 | } 5 | } 6 | 7 | class Bar < Foo { 8 | inBar() { 9 | print "in bar"; 10 | } 11 | } 12 | 13 | class Baz < Bar { 14 | inBaz() { 15 | print "in baz"; 16 | } 17 | } 18 | 19 | var baz = Baz(); 20 | baz.inFoo(); // expect: in foo 21 | baz.inBar(); // expect: in bar 22 | baz.inBaz(); // expect: in baz 23 | -------------------------------------------------------------------------------- /test/class/local_inherit_other.lox: -------------------------------------------------------------------------------- 1 | class A {} 2 | 3 | fun f() { 4 | class B < A {} 5 | return B; 6 | } 7 | 8 | print f(); // expect: B 9 | -------------------------------------------------------------------------------- /test/class/local_inherit_self.lox: -------------------------------------------------------------------------------- 1 | { 2 | class Foo < Foo {} // Error at 'Foo': A class can't inherit from itself. 3 | } 4 | // [c line 5] Error at end: Expect '}' after block. 5 | -------------------------------------------------------------------------------- /test/class/local_reference_self.lox: -------------------------------------------------------------------------------- 1 | { 2 | class Foo { 3 | returnSelf() { 4 | return Foo; 5 | } 6 | } 7 | 8 | print Foo().returnSelf(); // expect: Foo 9 | } 10 | -------------------------------------------------------------------------------- /test/class/reference_self.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | returnSelf() { 3 | return Foo; 4 | } 5 | } 6 | 7 | print Foo().returnSelf(); // expect: Foo 8 | -------------------------------------------------------------------------------- /test/closure/assign_to_closure.lox: -------------------------------------------------------------------------------- 1 | var f; 2 | var g; 3 | 4 | { 5 | var local = "local"; 6 | fun f_() { 7 | print local; 8 | local = "after f"; 9 | print local; 10 | } 11 | f = f_; 12 | 13 | fun g_() { 14 | print local; 15 | local = "after g"; 16 | print local; 17 | } 18 | g = g_; 19 | } 20 | 21 | f(); 22 | // expect: local 23 | // expect: after f 24 | 25 | g(); 26 | // expect: after f 27 | // expect: after g 28 | -------------------------------------------------------------------------------- /test/closure/assign_to_shadowed_later.lox: -------------------------------------------------------------------------------- 1 | var a = "global"; 2 | 3 | { 4 | fun assign() { 5 | a = "assigned"; 6 | } 7 | 8 | var a = "inner"; 9 | assign(); 10 | print a; // expect: inner 11 | } 12 | 13 | print a; // expect: assigned 14 | -------------------------------------------------------------------------------- /test/closure/close_over_function_parameter.lox: -------------------------------------------------------------------------------- 1 | var f; 2 | 3 | fun foo(param) { 4 | fun f_() { 5 | print param; 6 | } 7 | f = f_; 8 | } 9 | foo("param"); 10 | 11 | f(); // expect: param 12 | -------------------------------------------------------------------------------- /test/closure/close_over_later_variable.lox: -------------------------------------------------------------------------------- 1 | // This is a regression test. There was a bug where if an upvalue for an 2 | // earlier local (here "a") was captured *after* a later one ("b"), then it 3 | // would crash because it walked to the end of the upvalue list (correct), but 4 | // then didn't handle not finding the variable. 5 | 6 | fun f() { 7 | var a = "a"; 8 | var b = "b"; 9 | fun g() { 10 | print b; // expect: b 11 | print a; // expect: a 12 | } 13 | g(); 14 | } 15 | f(); 16 | -------------------------------------------------------------------------------- /test/closure/close_over_method_parameter.lox: -------------------------------------------------------------------------------- 1 | var f; 2 | 3 | class Foo { 4 | method(param) { 5 | fun f_() { 6 | print param; 7 | } 8 | f = f_; 9 | } 10 | } 11 | 12 | Foo().method("param"); 13 | f(); // expect: param 14 | -------------------------------------------------------------------------------- /test/closure/closed_closure_in_function.lox: -------------------------------------------------------------------------------- 1 | var f; 2 | 3 | { 4 | var local = "local"; 5 | fun f_() { 6 | print local; 7 | } 8 | f = f_; 9 | } 10 | 11 | f(); // expect: local 12 | -------------------------------------------------------------------------------- /test/closure/nested_closure.lox: -------------------------------------------------------------------------------- 1 | var f; 2 | 3 | fun f1() { 4 | var a = "a"; 5 | fun f2() { 6 | var b = "b"; 7 | fun f3() { 8 | var c = "c"; 9 | fun f4() { 10 | print a; 11 | print b; 12 | print c; 13 | } 14 | f = f4; 15 | } 16 | f3(); 17 | } 18 | f2(); 19 | } 20 | f1(); 21 | 22 | f(); 23 | // expect: a 24 | // expect: b 25 | // expect: c 26 | -------------------------------------------------------------------------------- /test/closure/open_closure_in_function.lox: -------------------------------------------------------------------------------- 1 | { 2 | var local = "local"; 3 | fun f() { 4 | print local; // expect: local 5 | } 6 | f(); 7 | } 8 | -------------------------------------------------------------------------------- /test/closure/reference_closure_multiple_times.lox: -------------------------------------------------------------------------------- 1 | var f; 2 | 3 | { 4 | var a = "a"; 5 | fun f_() { 6 | print a; 7 | print a; 8 | } 9 | f = f_; 10 | } 11 | 12 | f(); 13 | // expect: a 14 | // expect: a 15 | -------------------------------------------------------------------------------- /test/closure/reuse_closure_slot.lox: -------------------------------------------------------------------------------- 1 | { 2 | var f; 3 | 4 | { 5 | var a = "a"; 6 | fun f_() { print a; } 7 | f = f_; 8 | } 9 | 10 | { 11 | // Since a is out of scope, the local slot will be reused by b. Make sure 12 | // that f still closes over a. 13 | var b = "b"; 14 | f(); // expect: a 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/closure/shadow_closure_with_local.lox: -------------------------------------------------------------------------------- 1 | { 2 | var foo = "closure"; 3 | fun f() { 4 | { 5 | print foo; // expect: closure 6 | var foo = "shadow"; 7 | print foo; // expect: shadow 8 | } 9 | print foo; // expect: closure 10 | } 11 | f(); 12 | } 13 | -------------------------------------------------------------------------------- /test/closure/unused_closure.lox: -------------------------------------------------------------------------------- 1 | // This is a regression test. There was a bug where the VM would try to close 2 | // an upvalue even if the upvalue was never created because the codepath for 3 | // the closure was not executed. 4 | 5 | { 6 | var a = "a"; 7 | if (false) { 8 | fun foo() { a; } 9 | } 10 | } 11 | 12 | // If we get here, we didn't segfault when a went out of scope. 13 | print "ok"; // expect: ok 14 | -------------------------------------------------------------------------------- /test/closure/unused_later_closure.lox: -------------------------------------------------------------------------------- 1 | // This is a regression test. When closing upvalues for discarded locals, it 2 | // wouldn't make sure it discarded the upvalue for the correct stack slot. 3 | // 4 | // Here we create two locals that can be closed over, but only the first one 5 | // actually is. When "b" goes out of scope, we need to make sure we don't 6 | // prematurely close "a". 7 | var closure; 8 | 9 | { 10 | var a = "a"; 11 | 12 | { 13 | var b = "b"; 14 | fun returnA() { 15 | return a; 16 | } 17 | 18 | closure = returnA; 19 | 20 | if (false) { 21 | fun returnB() { 22 | return b; 23 | } 24 | } 25 | } 26 | 27 | print closure(); // expect: a 28 | } 29 | -------------------------------------------------------------------------------- /test/comments/line_at_eof.lox: -------------------------------------------------------------------------------- 1 | print "ok"; // expect: ok 2 | // comment -------------------------------------------------------------------------------- /test/comments/only_line_comment.lox: -------------------------------------------------------------------------------- 1 | // comment -------------------------------------------------------------------------------- /test/comments/only_line_comment_and_line.lox: -------------------------------------------------------------------------------- 1 | // comment 2 | -------------------------------------------------------------------------------- /test/comments/unicode.lox: -------------------------------------------------------------------------------- 1 | // Unicode characters are allowed in comments. 2 | // 3 | // Latin 1 Supplement: £§¶ÜÞ 4 | // Latin Extended-A: ĐĦŋœ 5 | // Latin Extended-B: ƂƢƩǁ 6 | // Other stuff: ឃᢆ᯽₪ℜ↩⊗┺░ 7 | // Emoji: ☃☺♣ 8 | 9 | print "ok"; // expect: ok 10 | -------------------------------------------------------------------------------- /test/constructor/arguments.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | init(a, b) { 3 | print "init"; // expect: init 4 | this.a = a; 5 | this.b = b; 6 | } 7 | } 8 | 9 | var foo = Foo(1, 2); 10 | print foo.a; // expect: 1 11 | print foo.b; // expect: 2 12 | -------------------------------------------------------------------------------- /test/constructor/call_init_early_return.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | init() { 3 | print "init"; 4 | return; 5 | print "nope"; 6 | } 7 | } 8 | 9 | var foo = Foo(); // expect: init 10 | print foo.init(); // expect: init 11 | // expect: Foo instance 12 | -------------------------------------------------------------------------------- /test/constructor/call_init_explicitly.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | init(arg) { 3 | print "Foo.init(" + arg + ")"; 4 | this.field = "init"; 5 | } 6 | } 7 | 8 | var foo = Foo("one"); // expect: Foo.init(one) 9 | foo.field = "field"; 10 | 11 | var foo2 = foo.init("two"); // expect: Foo.init(two) 12 | print foo2; // expect: Foo instance 13 | 14 | // Make sure init() doesn't create a fresh instance. 15 | print foo.field; // expect: init 16 | -------------------------------------------------------------------------------- /test/constructor/default.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | var foo = Foo(); 4 | print foo; // expect: Foo instance 5 | -------------------------------------------------------------------------------- /test/constructor/default_arguments.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | var foo = Foo(1, 2, 3); // expect runtime error: Expected 0 arguments but got 3. 4 | -------------------------------------------------------------------------------- /test/constructor/early_return.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | init() { 3 | print "init"; 4 | return; 5 | print "nope"; 6 | } 7 | } 8 | 9 | var foo = Foo(); // expect: init 10 | print foo; // expect: Foo instance 11 | -------------------------------------------------------------------------------- /test/constructor/extra_arguments.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | init(a, b) { 3 | this.a = a; 4 | this.b = b; 5 | } 6 | } 7 | 8 | var foo = Foo(1, 2, 3, 4); // expect runtime error: Expected 2 arguments but got 4. -------------------------------------------------------------------------------- /test/constructor/init_not_method.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | init(arg) { 3 | print "Foo.init(" + arg + ")"; 4 | this.field = "init"; 5 | } 6 | } 7 | 8 | fun init() { 9 | print "not initializer"; 10 | } 11 | 12 | init(); // expect: not initializer 13 | -------------------------------------------------------------------------------- /test/constructor/missing_arguments.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | init(a, b) {} 3 | } 4 | 5 | var foo = Foo(1); // expect runtime error: Expected 2 arguments but got 1. 6 | -------------------------------------------------------------------------------- /test/constructor/return_in_nested_function.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | init() { 3 | fun init() { 4 | return "bar"; 5 | } 6 | print init(); // expect: bar 7 | } 8 | } 9 | 10 | print Foo(); // expect: Foo instance 11 | -------------------------------------------------------------------------------- /test/constructor/return_value.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | init() { 3 | return "result"; // Error at 'return': Can't return a value from an initializer. 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/empty_file.lox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/munificent/craftinginterpreters/4a840f70f69c6ddd17cfef4f6964f8e1bcd8c3d4/test/empty_file.lox -------------------------------------------------------------------------------- /test/expressions/evaluate.lox: -------------------------------------------------------------------------------- 1 | // Note: This is just for the expression evaluating chapter which evaluates an 2 | // expression directly. 3 | (5 - (3 - 1)) + -1 4 | // expect: 2 5 | -------------------------------------------------------------------------------- /test/expressions/parse.lox: -------------------------------------------------------------------------------- 1 | // Note: This is just for the expression parsing chapter which prints the AST. 2 | (5 - (3 - 1)) + -1 3 | // expect: (+ (group (- 5.0 (group (- 3.0 1.0)))) (- 1.0)) 4 | -------------------------------------------------------------------------------- /test/field/call_function_field.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | fun bar(a, b) { 4 | print "bar"; 5 | print a; 6 | print b; 7 | } 8 | 9 | var foo = Foo(); 10 | foo.bar = bar; 11 | 12 | foo.bar(1, 2); 13 | // expect: bar 14 | // expect: 1 15 | // expect: 2 16 | -------------------------------------------------------------------------------- /test/field/call_nonfunction_field.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | var foo = Foo(); 4 | foo.bar = "not fn"; 5 | 6 | foo.bar(); // expect runtime error: Can only call functions and classes. 7 | -------------------------------------------------------------------------------- /test/field/get_and_set_method.lox: -------------------------------------------------------------------------------- 1 | // Bound methods have identity equality. 2 | class Foo { 3 | method(a) { 4 | print "method"; 5 | print a; 6 | } 7 | other(a) { 8 | print "other"; 9 | print a; 10 | } 11 | } 12 | 13 | var foo = Foo(); 14 | var method = foo.method; 15 | 16 | // Setting a property shadows the instance method. 17 | foo.method = foo.other; 18 | foo.method(1); 19 | // expect: other 20 | // expect: 1 21 | 22 | // The old method handle still points to the original method. 23 | method(2); 24 | // expect: method 25 | // expect: 2 26 | -------------------------------------------------------------------------------- /test/field/get_on_bool.lox: -------------------------------------------------------------------------------- 1 | true.foo; // expect runtime error: Only instances have properties. 2 | -------------------------------------------------------------------------------- /test/field/get_on_class.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | Foo.bar; // expect runtime error: Only instances have properties. 3 | -------------------------------------------------------------------------------- /test/field/get_on_function.lox: -------------------------------------------------------------------------------- 1 | fun foo() {} 2 | 3 | foo.bar; // expect runtime error: Only instances have properties. 4 | -------------------------------------------------------------------------------- /test/field/get_on_nil.lox: -------------------------------------------------------------------------------- 1 | nil.foo; // expect runtime error: Only instances have properties. 2 | -------------------------------------------------------------------------------- /test/field/get_on_num.lox: -------------------------------------------------------------------------------- 1 | 123.foo; // expect runtime error: Only instances have properties. 2 | -------------------------------------------------------------------------------- /test/field/get_on_string.lox: -------------------------------------------------------------------------------- 1 | "str".foo; // expect runtime error: Only instances have properties. 2 | -------------------------------------------------------------------------------- /test/field/method.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | bar(arg) { 3 | print arg; 4 | } 5 | } 6 | 7 | var bar = Foo().bar; 8 | print "got method"; // expect: got method 9 | bar("arg"); // expect: arg 10 | -------------------------------------------------------------------------------- /test/field/method_binds_this.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | sayName(a) { 3 | print this.name; 4 | print a; 5 | } 6 | } 7 | 8 | var foo1 = Foo(); 9 | foo1.name = "foo1"; 10 | 11 | var foo2 = Foo(); 12 | foo2.name = "foo2"; 13 | 14 | // Store the method reference on another object. 15 | foo2.fn = foo1.sayName; 16 | // Still retains original receiver. 17 | foo2.fn(1); 18 | // expect: foo1 19 | // expect: 1 20 | -------------------------------------------------------------------------------- /test/field/on_instance.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | var foo = Foo(); 4 | 5 | print foo.bar = "bar value"; // expect: bar value 6 | print foo.baz = "baz value"; // expect: baz value 7 | 8 | print foo.bar; // expect: bar value 9 | print foo.baz; // expect: baz value 10 | -------------------------------------------------------------------------------- /test/field/set_evaluation_order.lox: -------------------------------------------------------------------------------- 1 | undefined1.bar // expect runtime error: Undefined variable 'undefined1'. 2 | = undefined2; -------------------------------------------------------------------------------- /test/field/set_on_bool.lox: -------------------------------------------------------------------------------- 1 | true.foo = "value"; // expect runtime error: Only instances have fields. 2 | -------------------------------------------------------------------------------- /test/field/set_on_class.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | Foo.bar = "value"; // expect runtime error: Only instances have fields. 3 | -------------------------------------------------------------------------------- /test/field/set_on_function.lox: -------------------------------------------------------------------------------- 1 | fun foo() {} 2 | 3 | foo.bar = "value"; // expect runtime error: Only instances have fields. 4 | -------------------------------------------------------------------------------- /test/field/set_on_nil.lox: -------------------------------------------------------------------------------- 1 | nil.foo = "value"; // expect runtime error: Only instances have fields. 2 | -------------------------------------------------------------------------------- /test/field/set_on_num.lox: -------------------------------------------------------------------------------- 1 | 123.foo = "value"; // expect runtime error: Only instances have fields. 2 | -------------------------------------------------------------------------------- /test/field/set_on_string.lox: -------------------------------------------------------------------------------- 1 | "str".foo = "value"; // expect runtime error: Only instances have fields. 2 | -------------------------------------------------------------------------------- /test/field/undefined.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | var foo = Foo(); 3 | 4 | foo.bar; // expect runtime error: Undefined property 'bar'. 5 | -------------------------------------------------------------------------------- /test/for/class_in_body.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'class': Expect expression. 2 | for (;;) class Foo {} 3 | -------------------------------------------------------------------------------- /test/for/closure_in_body.lox: -------------------------------------------------------------------------------- 1 | var f1; 2 | var f2; 3 | var f3; 4 | 5 | for (var i = 1; i < 4; i = i + 1) { 6 | var j = i; 7 | fun f() { 8 | print i; 9 | print j; 10 | } 11 | 12 | if (j == 1) f1 = f; 13 | else if (j == 2) f2 = f; 14 | else f3 = f; 15 | } 16 | 17 | f1(); // expect: 4 18 | // expect: 1 19 | f2(); // expect: 4 20 | // expect: 2 21 | f3(); // expect: 4 22 | // expect: 3 23 | -------------------------------------------------------------------------------- /test/for/fun_in_body.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'fun': Expect expression. 2 | for (;;) fun foo() {} 3 | -------------------------------------------------------------------------------- /test/for/return_closure.lox: -------------------------------------------------------------------------------- 1 | fun f() { 2 | for (;;) { 3 | var i = "i"; 4 | fun g() { print i; } 5 | return g; 6 | } 7 | } 8 | 9 | var h = f(); 10 | h(); // expect: i 11 | -------------------------------------------------------------------------------- /test/for/return_inside.lox: -------------------------------------------------------------------------------- 1 | fun f() { 2 | for (;;) { 3 | var i = "i"; 4 | return i; 5 | } 6 | } 7 | 8 | print f(); 9 | // expect: i 10 | -------------------------------------------------------------------------------- /test/for/scope.lox: -------------------------------------------------------------------------------- 1 | { 2 | var i = "before"; 3 | 4 | // New variable is in inner scope. 5 | for (var i = 0; i < 1; i = i + 1) { 6 | print i; // expect: 0 7 | 8 | // Loop body is in second inner scope. 9 | var i = -1; 10 | print i; // expect: -1 11 | } 12 | } 13 | 14 | { 15 | // New variable shadows outer variable. 16 | for (var i = 0; i > 0; i = i + 1) {} 17 | 18 | // Goes out of scope after loop. 19 | var i = "after"; 20 | print i; // expect: after 21 | 22 | // Can reuse an existing variable. 23 | for (i = 0; i < 1; i = i + 1) { 24 | print i; // expect: 0 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/for/statement_condition.lox: -------------------------------------------------------------------------------- 1 | // [line 3] Error at '{': Expect expression. 2 | // [line 3] Error at ')': Expect ';' after expression. 3 | for (var a = 1; {}; a = a + 1) {} 4 | -------------------------------------------------------------------------------- /test/for/statement_increment.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at '{': Expect expression. 2 | for (var a = 1; a < 2; {}) {} 3 | -------------------------------------------------------------------------------- /test/for/statement_initializer.lox: -------------------------------------------------------------------------------- 1 | // [line 3] Error at '{': Expect expression. 2 | // [line 3] Error at ')': Expect ';' after expression. 3 | for ({}; a < 2; a = a + 1) {} 4 | -------------------------------------------------------------------------------- /test/for/syntax.lox: -------------------------------------------------------------------------------- 1 | // Single-expression body. 2 | for (var c = 0; c < 3;) print c = c + 1; 3 | // expect: 1 4 | // expect: 2 5 | // expect: 3 6 | 7 | // Block body. 8 | for (var a = 0; a < 3; a = a + 1) { 9 | print a; 10 | } 11 | // expect: 0 12 | // expect: 1 13 | // expect: 2 14 | 15 | // No clauses. 16 | fun foo() { 17 | for (;;) return "done"; 18 | } 19 | print foo(); // expect: done 20 | 21 | // No variable. 22 | var i = 0; 23 | for (; i < 2; i = i + 1) print i; 24 | // expect: 0 25 | // expect: 1 26 | 27 | // No condition. 28 | fun bar() { 29 | for (var i = 0;; i = i + 1) { 30 | print i; 31 | if (i >= 2) return; 32 | } 33 | } 34 | bar(); 35 | // expect: 0 36 | // expect: 1 37 | // expect: 2 38 | 39 | // No increment. 40 | for (var i = 0; i < 2;) { 41 | print i; 42 | i = i + 1; 43 | } 44 | // expect: 0 45 | // expect: 1 46 | 47 | // Statement bodies. 48 | for (; false;) if (true) 1; else 2; 49 | for (; false;) while (true) 1; 50 | for (; false;) for (;;) 1; 51 | -------------------------------------------------------------------------------- /test/for/var_in_body.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'var': Expect expression. 2 | for (;;) var foo; 3 | -------------------------------------------------------------------------------- /test/function/body_must_be_block.lox: -------------------------------------------------------------------------------- 1 | // [line 3] Error at '123': Expect '{' before function body. 2 | // [c line 4] Error at end: Expect '}' after block. 3 | fun f() 123; 4 | -------------------------------------------------------------------------------- /test/function/empty_body.lox: -------------------------------------------------------------------------------- 1 | fun f() {} 2 | print f(); // expect: nil 3 | -------------------------------------------------------------------------------- /test/function/extra_arguments.lox: -------------------------------------------------------------------------------- 1 | fun f(a, b) { 2 | print a; 3 | print b; 4 | } 5 | 6 | f(1, 2, 3, 4); // expect runtime error: Expected 2 arguments but got 4. 7 | -------------------------------------------------------------------------------- /test/function/local_mutual_recursion.lox: -------------------------------------------------------------------------------- 1 | { 2 | fun isEven(n) { 3 | if (n == 0) return true; 4 | return isOdd(n - 1); // expect runtime error: Undefined variable 'isOdd'. 5 | } 6 | 7 | fun isOdd(n) { 8 | if (n == 0) return false; 9 | return isEven(n - 1); 10 | } 11 | 12 | isEven(4); 13 | } -------------------------------------------------------------------------------- /test/function/local_recursion.lox: -------------------------------------------------------------------------------- 1 | { 2 | fun fib(n) { 3 | if (n < 2) return n; 4 | return fib(n - 1) + fib(n - 2); 5 | } 6 | 7 | print fib(8); // expect: 21 8 | } 9 | -------------------------------------------------------------------------------- /test/function/missing_arguments.lox: -------------------------------------------------------------------------------- 1 | fun f(a, b) {} 2 | 3 | f(1); // expect runtime error: Expected 2 arguments but got 1. 4 | -------------------------------------------------------------------------------- /test/function/missing_comma_in_parameters.lox: -------------------------------------------------------------------------------- 1 | // [line 3] Error at 'c': Expect ')' after parameters. 2 | // [c line 4] Error at end: Expect '}' after block. 3 | fun foo(a, b c, d, e, f) {} 4 | -------------------------------------------------------------------------------- /test/function/mutual_recursion.lox: -------------------------------------------------------------------------------- 1 | fun isEven(n) { 2 | if (n == 0) return true; 3 | return isOdd(n - 1); 4 | } 5 | 6 | fun isOdd(n) { 7 | if (n == 0) return false; 8 | return isEven(n - 1); 9 | } 10 | 11 | print isEven(4); // expect: true 12 | print isOdd(3); // expect: true 13 | -------------------------------------------------------------------------------- /test/function/nested_call_with_arguments.lox: -------------------------------------------------------------------------------- 1 | fun returnArg(arg) { 2 | return arg; 3 | } 4 | 5 | fun returnFunCallWithArg(func, arg) { 6 | return returnArg(func)(arg); 7 | } 8 | 9 | fun printArg(arg) { 10 | print arg; 11 | } 12 | 13 | returnFunCallWithArg(printArg, "hello world"); // expect: hello world 14 | -------------------------------------------------------------------------------- /test/function/parameters.lox: -------------------------------------------------------------------------------- 1 | fun f0() { return 0; } 2 | print f0(); // expect: 0 3 | 4 | fun f1(a) { return a; } 5 | print f1(1); // expect: 1 6 | 7 | fun f2(a, b) { return a + b; } 8 | print f2(1, 2); // expect: 3 9 | 10 | fun f3(a, b, c) { return a + b + c; } 11 | print f3(1, 2, 3); // expect: 6 12 | 13 | fun f4(a, b, c, d) { return a + b + c + d; } 14 | print f4(1, 2, 3, 4); // expect: 10 15 | 16 | fun f5(a, b, c, d, e) { return a + b + c + d + e; } 17 | print f5(1, 2, 3, 4, 5); // expect: 15 18 | 19 | fun f6(a, b, c, d, e, f) { return a + b + c + d + e + f; } 20 | print f6(1, 2, 3, 4, 5, 6); // expect: 21 21 | 22 | fun f7(a, b, c, d, e, f, g) { return a + b + c + d + e + f + g; } 23 | print f7(1, 2, 3, 4, 5, 6, 7); // expect: 28 24 | 25 | fun f8(a, b, c, d, e, f, g, h) { return a + b + c + d + e + f + g + h; } 26 | print f8(1, 2, 3, 4, 5, 6, 7, 8); // expect: 36 27 | -------------------------------------------------------------------------------- /test/function/print.lox: -------------------------------------------------------------------------------- 1 | fun foo() {} 2 | print foo; // expect: 3 | 4 | print clock; // expect: 5 | -------------------------------------------------------------------------------- /test/function/recursion.lox: -------------------------------------------------------------------------------- 1 | fun fib(n) { 2 | if (n < 2) return n; 3 | return fib(n - 1) + fib(n - 2); 4 | } 5 | 6 | print fib(8); // expect: 21 7 | -------------------------------------------------------------------------------- /test/if/class_in_else.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'class': Expect expression. 2 | if (true) "ok"; else class Foo {} 3 | -------------------------------------------------------------------------------- /test/if/class_in_then.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'class': Expect expression. 2 | if (true) class Foo {} 3 | -------------------------------------------------------------------------------- /test/if/dangling_else.lox: -------------------------------------------------------------------------------- 1 | // A dangling else binds to the right-most if. 2 | if (true) if (false) print "bad"; else print "good"; // expect: good 3 | if (false) if (true) print "bad"; else print "bad"; 4 | -------------------------------------------------------------------------------- /test/if/else.lox: -------------------------------------------------------------------------------- 1 | // Evaluate the 'else' expression if the condition is false. 2 | if (true) print "good"; else print "bad"; // expect: good 3 | if (false) print "bad"; else print "good"; // expect: good 4 | 5 | // Allow block body. 6 | if (false) nil; else { print "block"; } // expect: block 7 | -------------------------------------------------------------------------------- /test/if/fun_in_else.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'fun': Expect expression. 2 | if (true) "ok"; else fun foo() {} 3 | -------------------------------------------------------------------------------- /test/if/fun_in_then.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'fun': Expect expression. 2 | if (true) fun foo() {} 3 | -------------------------------------------------------------------------------- /test/if/if.lox: -------------------------------------------------------------------------------- 1 | // Evaluate the 'then' expression if the condition is true. 2 | if (true) print "good"; // expect: good 3 | if (false) print "bad"; 4 | 5 | // Allow block body. 6 | if (true) { print "block"; } // expect: block 7 | 8 | // Assignment in if condition. 9 | var a = false; 10 | if (a = true) print a; // expect: true 11 | -------------------------------------------------------------------------------- /test/if/truth.lox: -------------------------------------------------------------------------------- 1 | // False and nil are false. 2 | if (false) print "bad"; else print "false"; // expect: false 3 | if (nil) print "bad"; else print "nil"; // expect: nil 4 | 5 | // Everything else is true. 6 | if (true) print true; // expect: true 7 | if (0) print 0; // expect: 0 8 | if ("") print "empty"; // expect: empty 9 | -------------------------------------------------------------------------------- /test/if/var_in_else.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'var': Expect expression. 2 | if (true) "ok"; else var foo; 3 | -------------------------------------------------------------------------------- /test/if/var_in_then.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'var': Expect expression. 2 | if (true) var foo; 3 | -------------------------------------------------------------------------------- /test/inheritance/constructor.lox: -------------------------------------------------------------------------------- 1 | class A { 2 | init(param) { 3 | this.field = param; 4 | } 5 | 6 | test() { 7 | print this.field; 8 | } 9 | } 10 | 11 | class B < A {} 12 | 13 | var b = B("value"); 14 | b.test(); // expect: value 15 | -------------------------------------------------------------------------------- /test/inheritance/inherit_from_function.lox: -------------------------------------------------------------------------------- 1 | fun foo() {} 2 | 3 | class Subclass < foo {} // expect runtime error: Superclass must be a class. 4 | -------------------------------------------------------------------------------- /test/inheritance/inherit_from_nil.lox: -------------------------------------------------------------------------------- 1 | var Nil = nil; 2 | class Foo < Nil {} // expect runtime error: Superclass must be a class. 3 | -------------------------------------------------------------------------------- /test/inheritance/inherit_from_number.lox: -------------------------------------------------------------------------------- 1 | var Number = 123; 2 | class Foo < Number {} // expect runtime error: Superclass must be a class. 3 | -------------------------------------------------------------------------------- /test/inheritance/inherit_methods.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | methodOnFoo() { print "foo"; } 3 | override() { print "foo"; } 4 | } 5 | 6 | class Bar < Foo { 7 | methodOnBar() { print "bar"; } 8 | override() { print "bar"; } 9 | } 10 | 11 | var bar = Bar(); 12 | bar.methodOnFoo(); // expect: foo 13 | bar.methodOnBar(); // expect: bar 14 | bar.override(); // expect: bar 15 | -------------------------------------------------------------------------------- /test/inheritance/parenthesized_superclass.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | // [line 4] Error at '(': Expect superclass name. 4 | class Bar < (Foo) {} 5 | -------------------------------------------------------------------------------- /test/inheritance/set_fields_from_base_class.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | foo(a, b) { 3 | this.field1 = a; 4 | this.field2 = b; 5 | } 6 | 7 | fooPrint() { 8 | print this.field1; 9 | print this.field2; 10 | } 11 | } 12 | 13 | class Bar < Foo { 14 | bar(a, b) { 15 | this.field1 = a; 16 | this.field2 = b; 17 | } 18 | 19 | barPrint() { 20 | print this.field1; 21 | print this.field2; 22 | } 23 | } 24 | 25 | var bar = Bar(); 26 | bar.foo("foo 1", "foo 2"); 27 | bar.fooPrint(); 28 | // expect: foo 1 29 | // expect: foo 2 30 | 31 | bar.bar("bar 1", "bar 2"); 32 | bar.barPrint(); 33 | // expect: bar 1 34 | // expect: bar 2 35 | 36 | bar.fooPrint(); 37 | // expect: bar 1 38 | // expect: bar 2 39 | -------------------------------------------------------------------------------- /test/limit/no_reuse_constants.lox: -------------------------------------------------------------------------------- 1 | fun f() { 2 | 0; 1; 2; 3; 4; 5; 6; 7; 3 | 8; 9; 10; 11; 12; 13; 14; 15; 4 | 16; 17; 18; 19; 20; 21; 22; 23; 5 | 24; 25; 26; 27; 28; 29; 30; 31; 6 | 32; 33; 34; 35; 36; 37; 38; 39; 7 | 40; 41; 42; 43; 44; 45; 46; 47; 8 | 48; 49; 50; 51; 52; 53; 54; 55; 9 | 56; 57; 58; 59; 60; 61; 62; 63; 10 | 64; 65; 66; 67; 68; 69; 70; 71; 11 | 72; 73; 74; 75; 76; 77; 78; 79; 12 | 80; 81; 82; 83; 84; 85; 86; 87; 13 | 88; 89; 90; 91; 92; 93; 94; 95; 14 | 96; 97; 98; 99; 100; 101; 102; 103; 15 | 104; 105; 106; 107; 108; 109; 110; 111; 16 | 112; 113; 114; 115; 116; 117; 118; 119; 17 | 120; 121; 122; 123; 124; 125; 126; 127; 18 | 128; 129; 130; 131; 132; 133; 134; 135; 19 | 136; 137; 138; 139; 140; 141; 142; 143; 20 | 144; 145; 146; 147; 148; 149; 150; 151; 21 | 152; 153; 154; 155; 156; 157; 158; 159; 22 | 160; 161; 162; 163; 164; 165; 166; 167; 23 | 168; 169; 170; 171; 172; 173; 174; 175; 24 | 176; 177; 178; 179; 180; 181; 182; 183; 25 | 184; 185; 186; 187; 188; 189; 190; 191; 26 | 192; 193; 194; 195; 196; 197; 198; 199; 27 | 200; 201; 202; 203; 204; 205; 206; 207; 28 | 208; 209; 210; 211; 212; 213; 214; 215; 29 | 216; 217; 218; 219; 220; 221; 222; 223; 30 | 224; 225; 226; 227; 228; 229; 230; 231; 31 | 232; 233; 234; 235; 236; 237; 238; 239; 32 | 240; 241; 242; 243; 244; 245; 246; 247; 33 | 248; 249; 250; 251; 252; 253; 254; 255; 34 | 35 | 1; // Error at '1': Too many constants in one chunk. 36 | } 37 | -------------------------------------------------------------------------------- /test/limit/stack_overflow.lox: -------------------------------------------------------------------------------- 1 | fun foo() { 2 | var a1; 3 | var a2; 4 | var a3; 5 | var a4; 6 | var a5; 7 | var a6; 8 | var a7; 9 | var a8; 10 | var a9; 11 | var a10; 12 | var a11; 13 | var a12; 14 | var a13; 15 | var a14; 16 | var a15; 17 | var a16; 18 | foo(); // expect runtime error: Stack overflow. 19 | } 20 | 21 | foo(); 22 | -------------------------------------------------------------------------------- /test/limit/too_many_constants.lox: -------------------------------------------------------------------------------- 1 | fun f() { 2 | 0; 1; 2; 3; 4; 5; 6; 7; 3 | 8; 9; 10; 11; 12; 13; 14; 15; 4 | 16; 17; 18; 19; 20; 21; 22; 23; 5 | 24; 25; 26; 27; 28; 29; 30; 31; 6 | 32; 33; 34; 35; 36; 37; 38; 39; 7 | 40; 41; 42; 43; 44; 45; 46; 47; 8 | 48; 49; 50; 51; 52; 53; 54; 55; 9 | 56; 57; 58; 59; 60; 61; 62; 63; 10 | 64; 65; 66; 67; 68; 69; 70; 71; 11 | 72; 73; 74; 75; 76; 77; 78; 79; 12 | 80; 81; 82; 83; 84; 85; 86; 87; 13 | 88; 89; 90; 91; 92; 93; 94; 95; 14 | 96; 97; 98; 99; 100; 101; 102; 103; 15 | 104; 105; 106; 107; 108; 109; 110; 111; 16 | 112; 113; 114; 115; 116; 117; 118; 119; 17 | 120; 121; 122; 123; 124; 125; 126; 127; 18 | 128; 129; 130; 131; 132; 133; 134; 135; 19 | 136; 137; 138; 139; 140; 141; 142; 143; 20 | 144; 145; 146; 147; 148; 149; 150; 151; 21 | 152; 153; 154; 155; 156; 157; 158; 159; 22 | 160; 161; 162; 163; 164; 165; 166; 167; 23 | 168; 169; 170; 171; 172; 173; 174; 175; 24 | 176; 177; 178; 179; 180; 181; 182; 183; 25 | 184; 185; 186; 187; 188; 189; 190; 191; 26 | 192; 193; 194; 195; 196; 197; 198; 199; 27 | 200; 201; 202; 203; 204; 205; 206; 207; 28 | 208; 209; 210; 211; 212; 213; 214; 215; 29 | 216; 217; 218; 219; 220; 221; 222; 223; 30 | 224; 225; 226; 227; 228; 229; 230; 231; 31 | 232; 233; 234; 235; 236; 237; 238; 239; 32 | 240; 241; 242; 243; 244; 245; 246; 247; 33 | 248; 249; 250; 251; 252; 253; 254; 255; 34 | 35 | "oops"; // Error at '"oops"': Too many constants in one chunk. 36 | } 37 | -------------------------------------------------------------------------------- /test/logical_operator/and.lox: -------------------------------------------------------------------------------- 1 | // Note: These tests implicitly depend on ints being truthy. 2 | 3 | // Return the first non-true argument. 4 | print false and 1; // expect: false 5 | print true and 1; // expect: 1 6 | print 1 and 2 and false; // expect: false 7 | 8 | // Return the last argument if all are true. 9 | print 1 and true; // expect: true 10 | print 1 and 2 and 3; // expect: 3 11 | 12 | // Short-circuit at the first false argument. 13 | var a = "before"; 14 | var b = "before"; 15 | (a = true) and 16 | (b = false) and 17 | (a = "bad"); 18 | print a; // expect: true 19 | print b; // expect: false 20 | -------------------------------------------------------------------------------- /test/logical_operator/and_truth.lox: -------------------------------------------------------------------------------- 1 | // False and nil are false. 2 | print false and "bad"; // expect: false 3 | print nil and "bad"; // expect: nil 4 | 5 | // Everything else is true. 6 | print true and "ok"; // expect: ok 7 | print 0 and "ok"; // expect: ok 8 | print "" and "ok"; // expect: ok 9 | -------------------------------------------------------------------------------- /test/logical_operator/or.lox: -------------------------------------------------------------------------------- 1 | // Note: These tests implicitly depend on ints being truthy. 2 | 3 | // Return the first true argument. 4 | print 1 or true; // expect: 1 5 | print false or 1; // expect: 1 6 | print false or false or true; // expect: true 7 | 8 | // Return the last argument if all are false. 9 | print false or false; // expect: false 10 | print false or false or false; // expect: false 11 | 12 | // Short-circuit at the first true argument. 13 | var a = "before"; 14 | var b = "before"; 15 | (a = false) or 16 | (b = true) or 17 | (a = "bad"); 18 | print a; // expect: false 19 | print b; // expect: true 20 | -------------------------------------------------------------------------------- /test/logical_operator/or_truth.lox: -------------------------------------------------------------------------------- 1 | // False and nil are false. 2 | print false or "ok"; // expect: ok 3 | print nil or "ok"; // expect: ok 4 | 5 | // Everything else is true. 6 | print true or "ok"; // expect: true 7 | print 0 or "ok"; // expect: 0 8 | print "s" or "ok"; // expect: s 9 | -------------------------------------------------------------------------------- /test/method/arity.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | method0() { return "no args"; } 3 | method1(a) { return a; } 4 | method2(a, b) { return a + b; } 5 | method3(a, b, c) { return a + b + c; } 6 | method4(a, b, c, d) { return a + b + c + d; } 7 | method5(a, b, c, d, e) { return a + b + c + d + e; } 8 | method6(a, b, c, d, e, f) { return a + b + c + d + e + f; } 9 | method7(a, b, c, d, e, f, g) { return a + b + c + d + e + f + g; } 10 | method8(a, b, c, d, e, f, g, h) { return a + b + c + d + e + f + g + h; } 11 | } 12 | 13 | var foo = Foo(); 14 | print foo.method0(); // expect: no args 15 | print foo.method1(1); // expect: 1 16 | print foo.method2(1, 2); // expect: 3 17 | print foo.method3(1, 2, 3); // expect: 6 18 | print foo.method4(1, 2, 3, 4); // expect: 10 19 | print foo.method5(1, 2, 3, 4, 5); // expect: 15 20 | print foo.method6(1, 2, 3, 4, 5, 6); // expect: 21 21 | print foo.method7(1, 2, 3, 4, 5, 6, 7); // expect: 28 22 | print foo.method8(1, 2, 3, 4, 5, 6, 7, 8); // expect: 36 23 | -------------------------------------------------------------------------------- /test/method/empty_block.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | bar() {} 3 | } 4 | 5 | print Foo().bar(); // expect: nil 6 | -------------------------------------------------------------------------------- /test/method/extra_arguments.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | method(a, b) { 3 | print a; 4 | print b; 5 | } 6 | } 7 | 8 | Foo().method(1, 2, 3, 4); // expect runtime error: Expected 2 arguments but got 4. 9 | -------------------------------------------------------------------------------- /test/method/missing_arguments.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | method(a, b) {} 3 | } 4 | 5 | Foo().method(1); // expect runtime error: Expected 2 arguments but got 1. 6 | -------------------------------------------------------------------------------- /test/method/not_found.lox: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | Foo().unknown(); // expect runtime error: Undefined property 'unknown'. 4 | -------------------------------------------------------------------------------- /test/method/print_bound_method.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | method() { } 3 | } 4 | var foo = Foo(); 5 | print foo.method; // expect: 6 | -------------------------------------------------------------------------------- /test/method/refer_to_name.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | method() { 3 | print method; // expect runtime error: Undefined variable 'method'. 4 | } 5 | } 6 | 7 | Foo().method(); 8 | -------------------------------------------------------------------------------- /test/nil/literal.lox: -------------------------------------------------------------------------------- 1 | print nil; // expect: nil 2 | -------------------------------------------------------------------------------- /test/number/decimal_point_at_eof.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at end: Expect property name after '.'. 2 | 123. -------------------------------------------------------------------------------- /test/number/leading_dot.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at '.': Expect expression. 2 | .123; 3 | -------------------------------------------------------------------------------- /test/number/literals.lox: -------------------------------------------------------------------------------- 1 | print 123; // expect: 123 2 | print 987654; // expect: 987654 3 | print 0; // expect: 0 4 | print -0; // expect: -0 5 | 6 | print 123.456; // expect: 123.456 7 | print -0.001; // expect: -0.001 8 | -------------------------------------------------------------------------------- /test/number/nan_equality.lox: -------------------------------------------------------------------------------- 1 | var nan = 0/0; 2 | 3 | print nan == 0; // expect: false 4 | print nan != 1; // expect: true 5 | 6 | // NaN is not equal to self. 7 | print nan == nan; // expect: false 8 | print nan != nan; // expect: true 9 | -------------------------------------------------------------------------------- /test/number/trailing_dot.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at ';': Expect property name after '.'. 2 | 123.; 3 | -------------------------------------------------------------------------------- /test/operator/add.lox: -------------------------------------------------------------------------------- 1 | print 123 + 456; // expect: 579 2 | print "str" + "ing"; // expect: string 3 | -------------------------------------------------------------------------------- /test/operator/add_bool_nil.lox: -------------------------------------------------------------------------------- 1 | true + nil; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /test/operator/add_bool_num.lox: -------------------------------------------------------------------------------- 1 | true + 123; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /test/operator/add_bool_string.lox: -------------------------------------------------------------------------------- 1 | true + "s"; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /test/operator/add_nil_nil.lox: -------------------------------------------------------------------------------- 1 | nil + nil; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /test/operator/add_num_nil.lox: -------------------------------------------------------------------------------- 1 | 1 + nil; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /test/operator/add_string_nil.lox: -------------------------------------------------------------------------------- 1 | "s" + nil; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /test/operator/comparison.lox: -------------------------------------------------------------------------------- 1 | print 1 < 2; // expect: true 2 | print 2 < 2; // expect: false 3 | print 2 < 1; // expect: false 4 | 5 | print 1 <= 2; // expect: true 6 | print 2 <= 2; // expect: true 7 | print 2 <= 1; // expect: false 8 | 9 | print 1 > 2; // expect: false 10 | print 2 > 2; // expect: false 11 | print 2 > 1; // expect: true 12 | 13 | print 1 >= 2; // expect: false 14 | print 2 >= 2; // expect: true 15 | print 2 >= 1; // expect: true 16 | 17 | // Zero and negative zero compare the same. 18 | print 0 < -0; // expect: false 19 | print -0 < 0; // expect: false 20 | print 0 > -0; // expect: false 21 | print -0 > 0; // expect: false 22 | print 0 <= -0; // expect: true 23 | print -0 <= 0; // expect: true 24 | print 0 >= -0; // expect: true 25 | print -0 >= 0; // expect: true 26 | -------------------------------------------------------------------------------- /test/operator/divide.lox: -------------------------------------------------------------------------------- 1 | print 8 / 2; // expect: 4 2 | print 12.34 / 12.34; // expect: 1 3 | -------------------------------------------------------------------------------- /test/operator/divide_nonnum_num.lox: -------------------------------------------------------------------------------- 1 | "1" / 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/divide_num_nonnum.lox: -------------------------------------------------------------------------------- 1 | 1 / "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/equals.lox: -------------------------------------------------------------------------------- 1 | print nil == nil; // expect: true 2 | 3 | print true == true; // expect: true 4 | print true == false; // expect: false 5 | 6 | print 1 == 1; // expect: true 7 | print 1 == 2; // expect: false 8 | 9 | print "str" == "str"; // expect: true 10 | print "str" == "ing"; // expect: false 11 | 12 | print nil == false; // expect: false 13 | print false == 0; // expect: false 14 | print 0 == "0"; // expect: false 15 | -------------------------------------------------------------------------------- /test/operator/equals_class.lox: -------------------------------------------------------------------------------- 1 | // Bound methods have identity equality. 2 | class Foo {} 3 | class Bar {} 4 | 5 | print Foo == Foo; // expect: true 6 | print Foo == Bar; // expect: false 7 | print Bar == Foo; // expect: false 8 | print Bar == Bar; // expect: true 9 | 10 | print Foo == "Foo"; // expect: false 11 | print Foo == nil; // expect: false 12 | print Foo == 123; // expect: false 13 | print Foo == true; // expect: false 14 | -------------------------------------------------------------------------------- /test/operator/equals_method.lox: -------------------------------------------------------------------------------- 1 | // Bound methods have identity equality. 2 | class Foo { 3 | method() {} 4 | } 5 | 6 | var foo = Foo(); 7 | var fooMethod = foo.method; 8 | 9 | // Same bound method. 10 | print fooMethod == fooMethod; // expect: true 11 | 12 | // Different closurizations. 13 | print foo.method == foo.method; // expect: false 14 | -------------------------------------------------------------------------------- /test/operator/greater_nonnum_num.lox: -------------------------------------------------------------------------------- 1 | "1" > 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/greater_num_nonnum.lox: -------------------------------------------------------------------------------- 1 | 1 > "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/greater_or_equal_nonnum_num.lox: -------------------------------------------------------------------------------- 1 | "1" >= 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/greater_or_equal_num_nonnum.lox: -------------------------------------------------------------------------------- 1 | 1 >= "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/less_nonnum_num.lox: -------------------------------------------------------------------------------- 1 | "1" < 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/less_num_nonnum.lox: -------------------------------------------------------------------------------- 1 | 1 < "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/less_or_equal_nonnum_num.lox: -------------------------------------------------------------------------------- 1 | "1" <= 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/less_or_equal_num_nonnum.lox: -------------------------------------------------------------------------------- 1 | 1 <= "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/multiply.lox: -------------------------------------------------------------------------------- 1 | print 5 * 3; // expect: 15 2 | print 12.34 * 0.3; // expect: 3.702 3 | -------------------------------------------------------------------------------- /test/operator/multiply_nonnum_num.lox: -------------------------------------------------------------------------------- 1 | "1" * 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/multiply_num_nonnum.lox: -------------------------------------------------------------------------------- 1 | 1 * "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/negate.lox: -------------------------------------------------------------------------------- 1 | print -(3); // expect: -3 2 | print --(3); // expect: 3 3 | print ---(3); // expect: -3 4 | -------------------------------------------------------------------------------- /test/operator/negate_nonnum.lox: -------------------------------------------------------------------------------- 1 | -"s"; // expect runtime error: Operand must be a number. 2 | -------------------------------------------------------------------------------- /test/operator/not.lox: -------------------------------------------------------------------------------- 1 | print !true; // expect: false 2 | print !false; // expect: true 3 | print !!true; // expect: true 4 | 5 | print !123; // expect: false 6 | print !0; // expect: false 7 | 8 | print !nil; // expect: true 9 | 10 | print !""; // expect: false 11 | 12 | fun foo() {} 13 | print !foo; // expect: false 14 | -------------------------------------------------------------------------------- /test/operator/not_class.lox: -------------------------------------------------------------------------------- 1 | class Bar {} 2 | print !Bar; // expect: false 3 | print !Bar(); // expect: false 4 | -------------------------------------------------------------------------------- /test/operator/not_equals.lox: -------------------------------------------------------------------------------- 1 | print nil != nil; // expect: false 2 | 3 | print true != true; // expect: false 4 | print true != false; // expect: true 5 | 6 | print 1 != 1; // expect: false 7 | print 1 != 2; // expect: true 8 | 9 | print "str" != "str"; // expect: false 10 | print "str" != "ing"; // expect: true 11 | 12 | print nil != false; // expect: true 13 | print false != 0; // expect: true 14 | print 0 != "0"; // expect: true 15 | -------------------------------------------------------------------------------- /test/operator/subtract.lox: -------------------------------------------------------------------------------- 1 | print 4 - 3; // expect: 1 2 | print 1.2 - 1.2; // expect: 0 3 | -------------------------------------------------------------------------------- /test/operator/subtract_nonnum_num.lox: -------------------------------------------------------------------------------- 1 | "1" - 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/operator/subtract_num_nonnum.lox: -------------------------------------------------------------------------------- 1 | 1 - "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /test/precedence.lox: -------------------------------------------------------------------------------- 1 | // * has higher precedence than +. 2 | print 2 + 3 * 4; // expect: 14 3 | 4 | // * has higher precedence than -. 5 | print 20 - 3 * 4; // expect: 8 6 | 7 | // / has higher precedence than +. 8 | print 2 + 6 / 3; // expect: 4 9 | 10 | // / has higher precedence than -. 11 | print 2 - 6 / 3; // expect: 0 12 | 13 | // < has higher precedence than ==. 14 | print false == 2 < 1; // expect: true 15 | 16 | // > has higher precedence than ==. 17 | print false == 1 > 2; // expect: true 18 | 19 | // <= has higher precedence than ==. 20 | print false == 2 <= 1; // expect: true 21 | 22 | // >= has higher precedence than ==. 23 | print false == 1 >= 2; // expect: true 24 | 25 | // 1 - 1 is not space-sensitive. 26 | print 1 - 1; // expect: 0 27 | print 1 -1; // expect: 0 28 | print 1- 1; // expect: 0 29 | print 1-1; // expect: 0 30 | 31 | // Using () for grouping. 32 | print (2 * (6 - (2 + 2))); // expect: 4 33 | -------------------------------------------------------------------------------- /test/print/missing_argument.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at ';': Expect expression. 2 | print; 3 | -------------------------------------------------------------------------------- /test/regression/394.lox: -------------------------------------------------------------------------------- 1 | { 2 | class A {} 3 | class B < A {} 4 | print B; // expect: B 5 | } 6 | -------------------------------------------------------------------------------- /test/regression/40.lox: -------------------------------------------------------------------------------- 1 | fun caller(g) { 2 | g(); 3 | // g should be a function, not nil. 4 | print g == nil; // expect: false 5 | } 6 | 7 | fun callCaller() { 8 | var capturedVar = "before"; 9 | var a = "a"; 10 | 11 | fun f() { 12 | // Commenting the next line out prevents the bug! 13 | capturedVar = "after"; 14 | 15 | // Returning anything also fixes it, even nil: 16 | //return nil; 17 | } 18 | 19 | caller(f); 20 | } 21 | 22 | callCaller(); 23 | -------------------------------------------------------------------------------- /test/return/after_else.lox: -------------------------------------------------------------------------------- 1 | fun f() { 2 | if (false) "no"; else return "ok"; 3 | } 4 | 5 | print f(); // expect: ok 6 | -------------------------------------------------------------------------------- /test/return/after_if.lox: -------------------------------------------------------------------------------- 1 | fun f() { 2 | if (true) return "ok"; 3 | } 4 | 5 | print f(); // expect: ok 6 | -------------------------------------------------------------------------------- /test/return/after_while.lox: -------------------------------------------------------------------------------- 1 | fun f() { 2 | while (true) return "ok"; 3 | } 4 | 5 | print f(); // expect: ok 6 | -------------------------------------------------------------------------------- /test/return/at_top_level.lox: -------------------------------------------------------------------------------- 1 | return "wat"; // Error at 'return': Can't return from top-level code. 2 | -------------------------------------------------------------------------------- /test/return/in_function.lox: -------------------------------------------------------------------------------- 1 | fun f() { 2 | return "ok"; 3 | print "bad"; 4 | } 5 | 6 | print f(); // expect: ok 7 | -------------------------------------------------------------------------------- /test/return/in_method.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | method() { 3 | return "ok"; 4 | print "bad"; 5 | } 6 | } 7 | 8 | print Foo().method(); // expect: ok 9 | -------------------------------------------------------------------------------- /test/return/return_nil_if_no_value.lox: -------------------------------------------------------------------------------- 1 | fun f() { 2 | return; 3 | print "bad"; 4 | } 5 | 6 | print f(); // expect: nil 7 | -------------------------------------------------------------------------------- /test/scanning/identifiers.lox: -------------------------------------------------------------------------------- 1 | andy formless fo _ _123 _abc ab123 2 | abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_ 3 | 4 | // expect: IDENTIFIER andy null 5 | // expect: IDENTIFIER formless null 6 | // expect: IDENTIFIER fo null 7 | // expect: IDENTIFIER _ null 8 | // expect: IDENTIFIER _123 null 9 | // expect: IDENTIFIER _abc null 10 | // expect: IDENTIFIER ab123 null 11 | // expect: IDENTIFIER abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_ null 12 | // expect: EOF null 13 | -------------------------------------------------------------------------------- /test/scanning/keywords.lox: -------------------------------------------------------------------------------- 1 | and class else false for fun if nil or return super this true var while 2 | 3 | // expect: AND and null 4 | // expect: CLASS class null 5 | // expect: ELSE else null 6 | // expect: FALSE false null 7 | // expect: FOR for null 8 | // expect: FUN fun null 9 | // expect: IF if null 10 | // expect: NIL nil null 11 | // expect: OR or null 12 | // expect: RETURN return null 13 | // expect: SUPER super null 14 | // expect: THIS this null 15 | // expect: TRUE true null 16 | // expect: VAR var null 17 | // expect: WHILE while null 18 | // expect: EOF null 19 | -------------------------------------------------------------------------------- /test/scanning/numbers.lox: -------------------------------------------------------------------------------- 1 | 123 2 | 123.456 3 | .456 4 | 123. 5 | 6 | // expect: NUMBER 123 123.0 7 | // expect: NUMBER 123.456 123.456 8 | // expect: DOT . null 9 | // expect: NUMBER 456 456.0 10 | // expect: NUMBER 123 123.0 11 | // expect: DOT . null 12 | // expect: EOF null 13 | -------------------------------------------------------------------------------- /test/scanning/punctuators.lox: -------------------------------------------------------------------------------- 1 | (){};,+-*!===<=>=!=<>/. 2 | 3 | // expect: LEFT_PAREN ( null 4 | // expect: RIGHT_PAREN ) null 5 | // expect: LEFT_BRACE { null 6 | // expect: RIGHT_BRACE } null 7 | // expect: SEMICOLON ; null 8 | // expect: COMMA , null 9 | // expect: PLUS + null 10 | // expect: MINUS - null 11 | // expect: STAR * null 12 | // expect: BANG_EQUAL != null 13 | // expect: EQUAL_EQUAL == null 14 | // expect: LESS_EQUAL <= null 15 | // expect: GREATER_EQUAL >= null 16 | // expect: BANG_EQUAL != null 17 | // expect: LESS < null 18 | // expect: GREATER > null 19 | // expect: SLASH / null 20 | // expect: DOT . null 21 | // expect: EOF null 22 | -------------------------------------------------------------------------------- /test/scanning/strings.lox: -------------------------------------------------------------------------------- 1 | "" 2 | "string" 3 | 4 | // expect: STRING "" 5 | // expect: STRING "string" string 6 | // expect: EOF null -------------------------------------------------------------------------------- /test/scanning/whitespace.lox: -------------------------------------------------------------------------------- 1 | space tabs newlines 2 | 3 | 4 | 5 | 6 | end 7 | 8 | // expect: IDENTIFIER space null 9 | // expect: IDENTIFIER tabs null 10 | // expect: IDENTIFIER newlines null 11 | // expect: IDENTIFIER end null 12 | // expect: EOF null 13 | -------------------------------------------------------------------------------- /test/string/error_after_multiline.lox: -------------------------------------------------------------------------------- 1 | // Tests that we correctly track the line info across multiline strings. 2 | var a = "1 3 | 2 4 | 3 5 | "; 6 | 7 | err; // // expect runtime error: Undefined variable 'err'. -------------------------------------------------------------------------------- /test/string/literals.lox: -------------------------------------------------------------------------------- 1 | print "(" + "" + ")"; // expect: () 2 | print "a string"; // expect: a string 3 | 4 | // Non-ASCII. 5 | print "A~¶Þॐஃ"; // expect: A~¶Þॐஃ 6 | -------------------------------------------------------------------------------- /test/string/multiline.lox: -------------------------------------------------------------------------------- 1 | var a = "1 2 | 2 3 | 3"; 4 | print a; 5 | // expect: 1 6 | // expect: 2 7 | // expect: 3 8 | -------------------------------------------------------------------------------- /test/string/unterminated.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error: Unterminated string. 2 | "this string has no close quote -------------------------------------------------------------------------------- /test/super/bound_method.lox: -------------------------------------------------------------------------------- 1 | class A { 2 | method(arg) { 3 | print "A.method(" + arg + ")"; 4 | } 5 | } 6 | 7 | class B < A { 8 | getClosure() { 9 | return super.method; 10 | } 11 | 12 | method(arg) { 13 | print "B.method(" + arg + ")"; 14 | } 15 | } 16 | 17 | 18 | var closure = B().getClosure(); 19 | closure("arg"); // expect: A.method(arg) 20 | -------------------------------------------------------------------------------- /test/super/call_other_method.lox: -------------------------------------------------------------------------------- 1 | class Base { 2 | foo() { 3 | print "Base.foo()"; 4 | } 5 | } 6 | 7 | class Derived < Base { 8 | bar() { 9 | print "Derived.bar()"; 10 | super.foo(); 11 | } 12 | } 13 | 14 | Derived().bar(); 15 | // expect: Derived.bar() 16 | // expect: Base.foo() 17 | -------------------------------------------------------------------------------- /test/super/call_same_method.lox: -------------------------------------------------------------------------------- 1 | class Base { 2 | foo() { 3 | print "Base.foo()"; 4 | } 5 | } 6 | 7 | class Derived < Base { 8 | foo() { 9 | print "Derived.foo()"; 10 | super.foo(); 11 | } 12 | } 13 | 14 | Derived().foo(); 15 | // expect: Derived.foo() 16 | // expect: Base.foo() 17 | -------------------------------------------------------------------------------- /test/super/closure.lox: -------------------------------------------------------------------------------- 1 | class Base { 2 | toString() { return "Base"; } 3 | } 4 | 5 | class Derived < Base { 6 | getClosure() { 7 | fun closure() { 8 | return super.toString(); 9 | } 10 | return closure; 11 | } 12 | 13 | toString() { return "Derived"; } 14 | } 15 | 16 | var closure = Derived().getClosure(); 17 | print closure(); // expect: Base 18 | -------------------------------------------------------------------------------- /test/super/constructor.lox: -------------------------------------------------------------------------------- 1 | class Base { 2 | init(a, b) { 3 | print "Base.init(" + a + ", " + b + ")"; 4 | } 5 | } 6 | 7 | class Derived < Base { 8 | init() { 9 | print "Derived.init()"; 10 | super.init("a", "b"); 11 | } 12 | } 13 | 14 | Derived(); 15 | // expect: Derived.init() 16 | // expect: Base.init(a, b) 17 | -------------------------------------------------------------------------------- /test/super/extra_arguments.lox: -------------------------------------------------------------------------------- 1 | class Base { 2 | foo(a, b) { 3 | print "Base.foo(" + a + ", " + b + ")"; 4 | } 5 | } 6 | 7 | class Derived < Base { 8 | foo() { 9 | print "Derived.foo()"; // expect: Derived.foo() 10 | super.foo("a", "b", "c", "d"); // expect runtime error: Expected 2 arguments but got 4. 11 | } 12 | } 13 | 14 | Derived().foo(); 15 | -------------------------------------------------------------------------------- /test/super/indirectly_inherited.lox: -------------------------------------------------------------------------------- 1 | class A { 2 | foo() { 3 | print "A.foo()"; 4 | } 5 | } 6 | 7 | class B < A {} 8 | 9 | class C < B { 10 | foo() { 11 | print "C.foo()"; 12 | super.foo(); 13 | } 14 | } 15 | 16 | C().foo(); 17 | // expect: C.foo() 18 | // expect: A.foo() 19 | -------------------------------------------------------------------------------- /test/super/missing_arguments.lox: -------------------------------------------------------------------------------- 1 | class Base { 2 | foo(a, b) { 3 | print "Base.foo(" + a + ", " + b + ")"; 4 | } 5 | } 6 | 7 | class Derived < Base { 8 | foo() { 9 | super.foo(1); // expect runtime error: Expected 2 arguments but got 1. 10 | } 11 | } 12 | 13 | Derived().foo(); 14 | -------------------------------------------------------------------------------- /test/super/no_superclass_bind.lox: -------------------------------------------------------------------------------- 1 | class Base { 2 | foo() { 3 | super.doesNotExist; // Error at 'super': Can't use 'super' in a class with no superclass. 4 | } 5 | } 6 | 7 | Base().foo(); 8 | -------------------------------------------------------------------------------- /test/super/no_superclass_call.lox: -------------------------------------------------------------------------------- 1 | class Base { 2 | foo() { 3 | super.doesNotExist(1); // Error at 'super': Can't use 'super' in a class with no superclass. 4 | } 5 | } 6 | 7 | Base().foo(); 8 | -------------------------------------------------------------------------------- /test/super/no_superclass_method.lox: -------------------------------------------------------------------------------- 1 | class Base {} 2 | 3 | class Derived < Base { 4 | foo() { 5 | super.doesNotExist(1); // expect runtime error: Undefined property 'doesNotExist'. 6 | } 7 | } 8 | 9 | Derived().foo(); 10 | -------------------------------------------------------------------------------- /test/super/parenthesized.lox: -------------------------------------------------------------------------------- 1 | class A { 2 | method() {} 3 | } 4 | 5 | class B < A { 6 | method() { 7 | // [line 8] Error at ')': Expect '.' after 'super'. 8 | (super).method(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/super/reassign_superclass.lox: -------------------------------------------------------------------------------- 1 | class Base { 2 | method() { 3 | print "Base.method()"; 4 | } 5 | } 6 | 7 | class Derived < Base { 8 | method() { 9 | super.method(); 10 | } 11 | } 12 | 13 | class OtherBase { 14 | method() { 15 | print "OtherBase.method()"; 16 | } 17 | } 18 | 19 | var derived = Derived(); 20 | derived.method(); // expect: Base.method() 21 | Base = OtherBase; 22 | derived.method(); // expect: Base.method() 23 | -------------------------------------------------------------------------------- /test/super/super_at_top_level.lox: -------------------------------------------------------------------------------- 1 | super.foo("bar"); // Error at 'super': Can't use 'super' outside of a class. 2 | super.foo; // Error at 'super': Can't use 'super' outside of a class. -------------------------------------------------------------------------------- /test/super/super_in_closure_in_inherited_method.lox: -------------------------------------------------------------------------------- 1 | class A { 2 | say() { 3 | print "A"; 4 | } 5 | } 6 | 7 | class B < A { 8 | getClosure() { 9 | fun closure() { 10 | super.say(); 11 | } 12 | return closure; 13 | } 14 | 15 | say() { 16 | print "B"; 17 | } 18 | } 19 | 20 | class C < B { 21 | say() { 22 | print "C"; 23 | } 24 | } 25 | 26 | C().getClosure()(); // expect: A 27 | -------------------------------------------------------------------------------- /test/super/super_in_inherited_method.lox: -------------------------------------------------------------------------------- 1 | class A { 2 | say() { 3 | print "A"; 4 | } 5 | } 6 | 7 | class B < A { 8 | test() { 9 | super.say(); 10 | } 11 | 12 | say() { 13 | print "B"; 14 | } 15 | } 16 | 17 | class C < B { 18 | say() { 19 | print "C"; 20 | } 21 | } 22 | 23 | C().test(); // expect: A 24 | -------------------------------------------------------------------------------- /test/super/super_in_top_level_function.lox: -------------------------------------------------------------------------------- 1 | super.bar(); // Error at 'super': Can't use 'super' outside of a class. 2 | fun foo() { 3 | } -------------------------------------------------------------------------------- /test/super/super_without_dot.lox: -------------------------------------------------------------------------------- 1 | class A {} 2 | 3 | class B < A { 4 | method() { 5 | // [line 6] Error at ';': Expect '.' after 'super'. 6 | super; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/super/super_without_name.lox: -------------------------------------------------------------------------------- 1 | class A {} 2 | 3 | class B < A { 4 | method() { 5 | super.; // Error at ';': Expect superclass method name. 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/super/this_in_superclass_method.lox: -------------------------------------------------------------------------------- 1 | class Base { 2 | init(a) { 3 | this.a = a; 4 | } 5 | } 6 | 7 | class Derived < Base { 8 | init(a, b) { 9 | super.init(a); 10 | this.b = b; 11 | } 12 | } 13 | 14 | var derived = Derived("a", "b"); 15 | print derived.a; // expect: a 16 | print derived.b; // expect: b 17 | -------------------------------------------------------------------------------- /test/this/closure.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | getClosure() { 3 | fun closure() { 4 | return this.toString(); 5 | } 6 | return closure; 7 | } 8 | 9 | toString() { return "Foo"; } 10 | } 11 | 12 | var closure = Foo().getClosure(); 13 | print closure(); // expect: Foo 14 | -------------------------------------------------------------------------------- /test/this/nested_class.lox: -------------------------------------------------------------------------------- 1 | class Outer { 2 | method() { 3 | print this; // expect: Outer instance 4 | 5 | fun f() { 6 | print this; // expect: Outer instance 7 | 8 | class Inner { 9 | method() { 10 | print this; // expect: Inner instance 11 | } 12 | } 13 | 14 | Inner().method(); 15 | } 16 | f(); 17 | } 18 | } 19 | 20 | Outer().method(); 21 | -------------------------------------------------------------------------------- /test/this/nested_closure.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | getClosure() { 3 | fun f() { 4 | fun g() { 5 | fun h() { 6 | return this.toString(); 7 | } 8 | return h; 9 | } 10 | return g; 11 | } 12 | return f; 13 | } 14 | 15 | toString() { return "Foo"; } 16 | } 17 | 18 | var closure = Foo().getClosure(); 19 | print closure()()(); // expect: Foo 20 | -------------------------------------------------------------------------------- /test/this/this_at_top_level.lox: -------------------------------------------------------------------------------- 1 | this; // Error at 'this': Can't use 'this' outside of a class. 2 | -------------------------------------------------------------------------------- /test/this/this_in_method.lox: -------------------------------------------------------------------------------- 1 | class Foo { 2 | bar() { return this; } 3 | baz() { return "baz"; } 4 | } 5 | 6 | print Foo().bar().baz(); // expect: baz 7 | -------------------------------------------------------------------------------- /test/this/this_in_top_level_function.lox: -------------------------------------------------------------------------------- 1 | fun foo() { 2 | this; // Error at 'this': Can't use 'this' outside of a class. 3 | } 4 | -------------------------------------------------------------------------------- /test/unexpected_character.lox: -------------------------------------------------------------------------------- 1 | // [line 3] Error: Unexpected character. 2 | // [java line 3] Error at 'b': Expect ')' after arguments. 3 | foo(a | b); 4 | -------------------------------------------------------------------------------- /test/variable/collide_with_parameter.lox: -------------------------------------------------------------------------------- 1 | fun foo(a) { 2 | var a; // Error at 'a': Already a variable with this name in this scope. 3 | } 4 | -------------------------------------------------------------------------------- /test/variable/duplicate_local.lox: -------------------------------------------------------------------------------- 1 | { 2 | var a = "value"; 3 | var a = "other"; // Error at 'a': Already a variable with this name in this scope. 4 | } 5 | -------------------------------------------------------------------------------- /test/variable/duplicate_parameter.lox: -------------------------------------------------------------------------------- 1 | fun foo(arg, 2 | arg) { // Error at 'arg': Already a variable with this name in this scope. 3 | "body"; 4 | } 5 | -------------------------------------------------------------------------------- /test/variable/early_bound.lox: -------------------------------------------------------------------------------- 1 | var a = "outer"; 2 | { 3 | fun foo() { 4 | print a; 5 | } 6 | 7 | foo(); // expect: outer 8 | var a = "inner"; 9 | foo(); // expect: outer 10 | } 11 | -------------------------------------------------------------------------------- /test/variable/in_middle_of_block.lox: -------------------------------------------------------------------------------- 1 | { 2 | var a = "a"; 3 | print a; // expect: a 4 | var b = a + " b"; 5 | print b; // expect: a b 6 | var c = a + " c"; 7 | print c; // expect: a c 8 | var d = b + " d"; 9 | print d; // expect: a b d 10 | } 11 | -------------------------------------------------------------------------------- /test/variable/in_nested_block.lox: -------------------------------------------------------------------------------- 1 | { 2 | var a = "outer"; 3 | { 4 | print a; // expect: outer 5 | } 6 | } -------------------------------------------------------------------------------- /test/variable/local_from_method.lox: -------------------------------------------------------------------------------- 1 | var foo = "variable"; 2 | 3 | class Foo { 4 | method() { 5 | print foo; 6 | } 7 | } 8 | 9 | Foo().method(); // expect: variable 10 | -------------------------------------------------------------------------------- /test/variable/redeclare_global.lox: -------------------------------------------------------------------------------- 1 | var a = "1"; 2 | var a; 3 | print a; // expect: nil 4 | -------------------------------------------------------------------------------- /test/variable/redefine_global.lox: -------------------------------------------------------------------------------- 1 | var a = "1"; 2 | var a = "2"; 3 | print a; // expect: 2 4 | -------------------------------------------------------------------------------- /test/variable/scope_reuse_in_different_blocks.lox: -------------------------------------------------------------------------------- 1 | { 2 | var a = "first"; 3 | print a; // expect: first 4 | } 5 | 6 | { 7 | var a = "second"; 8 | print a; // expect: second 9 | } 10 | -------------------------------------------------------------------------------- /test/variable/shadow_and_local.lox: -------------------------------------------------------------------------------- 1 | { 2 | var a = "outer"; 3 | { 4 | print a; // expect: outer 5 | var a = "inner"; 6 | print a; // expect: inner 7 | } 8 | } -------------------------------------------------------------------------------- /test/variable/shadow_global.lox: -------------------------------------------------------------------------------- 1 | var a = "global"; 2 | { 3 | var a = "shadow"; 4 | print a; // expect: shadow 5 | } 6 | print a; // expect: global 7 | -------------------------------------------------------------------------------- /test/variable/shadow_local.lox: -------------------------------------------------------------------------------- 1 | { 2 | var a = "local"; 3 | { 4 | var a = "shadow"; 5 | print a; // expect: shadow 6 | } 7 | print a; // expect: local 8 | } 9 | -------------------------------------------------------------------------------- /test/variable/undefined_global.lox: -------------------------------------------------------------------------------- 1 | print notDefined; // expect runtime error: Undefined variable 'notDefined'. 2 | -------------------------------------------------------------------------------- /test/variable/undefined_local.lox: -------------------------------------------------------------------------------- 1 | { 2 | print notDefined; // expect runtime error: Undefined variable 'notDefined'. 3 | } 4 | -------------------------------------------------------------------------------- /test/variable/uninitialized.lox: -------------------------------------------------------------------------------- 1 | var a; 2 | print a; // expect: nil 3 | -------------------------------------------------------------------------------- /test/variable/unreached_undefined.lox: -------------------------------------------------------------------------------- 1 | if (false) { 2 | print notDefined; 3 | } 4 | 5 | print "ok"; // expect: ok 6 | -------------------------------------------------------------------------------- /test/variable/use_false_as_var.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'false': Expect variable name. 2 | var false = "value"; 3 | -------------------------------------------------------------------------------- /test/variable/use_global_in_initializer.lox: -------------------------------------------------------------------------------- 1 | var a = "value"; 2 | var a = a; 3 | print a; // expect: value 4 | -------------------------------------------------------------------------------- /test/variable/use_local_in_initializer.lox: -------------------------------------------------------------------------------- 1 | var a = "outer"; 2 | { 3 | var a = a; // Error at 'a': Can't read local variable in its own initializer. 4 | } 5 | -------------------------------------------------------------------------------- /test/variable/use_nil_as_var.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'nil': Expect variable name. 2 | var nil = "value"; 3 | -------------------------------------------------------------------------------- /test/variable/use_this_as_var.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'this': Expect variable name. 2 | var this = "value"; 3 | -------------------------------------------------------------------------------- /test/while/class_in_body.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'class': Expect expression. 2 | while (true) class Foo {} 3 | -------------------------------------------------------------------------------- /test/while/closure_in_body.lox: -------------------------------------------------------------------------------- 1 | var f1; 2 | var f2; 3 | var f3; 4 | 5 | var i = 1; 6 | while (i < 4) { 7 | var j = i; 8 | fun f() { print j; } 9 | 10 | if (j == 1) f1 = f; 11 | else if (j == 2) f2 = f; 12 | else f3 = f; 13 | 14 | i = i + 1; 15 | } 16 | 17 | f1(); // expect: 1 18 | f2(); // expect: 2 19 | f3(); // expect: 3 20 | -------------------------------------------------------------------------------- /test/while/fun_in_body.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'fun': Expect expression. 2 | while (true) fun foo() {} 3 | -------------------------------------------------------------------------------- /test/while/return_closure.lox: -------------------------------------------------------------------------------- 1 | fun f() { 2 | while (true) { 3 | var i = "i"; 4 | fun g() { print i; } 5 | return g; 6 | } 7 | } 8 | 9 | var h = f(); 10 | h(); // expect: i 11 | -------------------------------------------------------------------------------- /test/while/return_inside.lox: -------------------------------------------------------------------------------- 1 | fun f() { 2 | while (true) { 3 | var i = "i"; 4 | return i; 5 | } 6 | } 7 | 8 | print f(); 9 | // expect: i 10 | -------------------------------------------------------------------------------- /test/while/syntax.lox: -------------------------------------------------------------------------------- 1 | // Single-expression body. 2 | var c = 0; 3 | while (c < 3) print c = c + 1; 4 | // expect: 1 5 | // expect: 2 6 | // expect: 3 7 | 8 | // Block body. 9 | var a = 0; 10 | while (a < 3) { 11 | print a; 12 | a = a + 1; 13 | } 14 | // expect: 0 15 | // expect: 1 16 | // expect: 2 17 | 18 | // Statement bodies. 19 | while (false) if (true) 1; else 2; 20 | while (false) while (true) 1; 21 | while (false) for (;;) 1; 22 | -------------------------------------------------------------------------------- /test/while/var_in_body.lox: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'var': Expect expression. 2 | while (true) var foo; 3 | -------------------------------------------------------------------------------- /tool/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | analyzer: 2 | strong-mode: 3 | # Close, but still false positives around clamp(). 4 | implicit-casts: false 5 | # Too many false positives. 6 | implicit-dynamic: false 7 | -------------------------------------------------------------------------------- /tool/bin/split_chapters.dart: -------------------------------------------------------------------------------- 1 | import 'package:tool/src/book.dart'; 2 | import 'package:tool/src/split_chapter.dart'; 3 | 4 | void main(List arguments) { 5 | var book = Book(); 6 | for (var page in book.pages) { 7 | if (page.language == null) continue; 8 | splitChapter(book, page); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tool/lib/src/format.dart: -------------------------------------------------------------------------------- 1 | /// The book format being rendered to. 2 | enum Format { 3 | /// HTML for the web. 4 | web, 5 | 6 | /// XML for importing into InDesign. 7 | print, 8 | } 9 | 10 | extension FormatExtension on Format { 11 | bool get isWeb => this == Format.web; 12 | bool get isPrint => this == Format.print; 13 | } 14 | -------------------------------------------------------------------------------- /tool/lib/src/markdown/block_syntax.dart: -------------------------------------------------------------------------------- 1 | import 'package:markdown/markdown.dart'; 2 | 3 | import '../format.dart'; 4 | import '../page.dart'; 5 | 6 | /// Parses atx-style headers like `## Header` and gives them the book's special 7 | /// handling: 8 | /// 9 | /// - Generates anchor links. 10 | /// - Includes the section numbers. 11 | class BookHeaderSyntax extends BlockSyntax { 12 | /// Leading `#` define atx-style headers. 13 | static final _headerPattern = RegExp(r'^(#{1,6}) (.*)$'); 14 | 15 | final Page _page; 16 | final Format _format; 17 | 18 | RegExp get pattern => _headerPattern; 19 | 20 | BookHeaderSyntax(this._page, this._format); 21 | 22 | Node parse(BlockParser parser) { 23 | var header = _page.headers[parser.current]; 24 | parser.advance(); 25 | 26 | if (_format.isPrint) { 27 | return Element("h${header.level}", [UnparsedContent(header.name)]); 28 | } 29 | 30 | var number = ""; 31 | if (!header.isSpecial) { 32 | number = "${_page.numberString} . ${header.headerIndex}"; 33 | if (header.subheaderIndex != null) { 34 | number += " . ${header.subheaderIndex}"; 35 | } 36 | } 37 | 38 | var link = Element("a", [ 39 | if (!header.isSpecial) Element("small", [Text(number)]), 40 | UnparsedContent(header.name) 41 | ]); 42 | link.attributes["href"] = "#${header.anchor}"; 43 | link.attributes["id"] = header.anchor; 44 | 45 | return Element("h${header.level}", [link]); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tool/lib/src/markdown/markdown.dart: -------------------------------------------------------------------------------- 1 | import 'package:markdown/markdown.dart' hide HtmlRenderer; 2 | 3 | import '../book.dart'; 4 | import '../format.dart'; 5 | import '../page.dart'; 6 | import 'block_syntax.dart'; 7 | import 'code_syntax.dart'; 8 | import 'html_renderer.dart'; 9 | import 'inline_syntax.dart'; 10 | import 'xml_renderer.dart'; 11 | 12 | String renderMarkdown(Book book, Page page, List lines, Format format) { 13 | var document = Document(blockSyntaxes: [ 14 | BookHeaderSyntax(page, format), 15 | CodeTagBlockSyntax(book, page, format), 16 | HighlightedCodeBlockSyntax(format), 17 | ], inlineSyntaxes: [ 18 | // Put inline Markdown code syntax before our smart quotes so that 19 | // quotes inside `code` spans don't get smartened. 20 | CodeSyntax(), 21 | EllipseSyntax(format), 22 | ApostropheSyntax(format), 23 | SmartQuoteSyntax(format), 24 | EmDashSyntax(format), 25 | if (format.isPrint) NewlineSyntax(), 26 | ], extensionSet: ExtensionSet.gitHubFlavored); 27 | 28 | var ast = document.parseLines(lines); 29 | if (format.isPrint) { 30 | return XmlRenderer().render(ast); 31 | } else { 32 | return HtmlRenderer().render(ast); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tool/lib/src/syntax/language.dart: -------------------------------------------------------------------------------- 1 | import 'rule.dart'; 2 | 3 | /// Defines the syntax rules for a single programming language. 4 | class Language { 5 | final Map words = {}; 6 | final List rules; 7 | 8 | Language({String keywords, String types, List this.rules}) { 9 | keywordType(String wordList, String type) { 10 | if (wordList == null) return; 11 | for (var word in wordList.split(" ")) { 12 | words[word] = type; 13 | } 14 | } 15 | 16 | keywordType(keywords, "k"); 17 | keywordType(types, "t"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tool/lib/src/term.dart: -------------------------------------------------------------------------------- 1 | /// Utilities for printing to the terminal. 2 | import 'dart:io'; 3 | 4 | final _cyan = _ansi('\u001b[36m'); 5 | final _gray = _ansi('\u001b[1;30m'); 6 | final _green = _ansi('\u001b[32m'); 7 | final _magenta = _ansi('\u001b[35m'); 8 | final _pink = _ansi('\u001b[91m'); 9 | final _red = _ansi('\u001b[31m'); 10 | final _yellow = _ansi('\u001b[33m'); 11 | final _none = _ansi('\u001b[0m'); 12 | final _resetColor = _ansi('\u001b[39m'); 13 | 14 | String cyan(Object message) => "$_cyan$message$_none"; 15 | String gray(Object message) => "$_gray$message$_none"; 16 | String green(Object message) => "$_green$message$_resetColor"; 17 | String magenta(Object message) => "$_magenta$message$_resetColor"; 18 | String pink(Object message) => "$_pink$message$_resetColor"; 19 | String red(Object message) => "$_red$message$_resetColor"; 20 | String yellow(Object message) => "$_yellow$message$_resetColor"; 21 | 22 | void clearLine() { 23 | if (_allowAnsi) { 24 | stdout.write("\u001b[2K\r"); 25 | } else { 26 | print(""); 27 | } 28 | } 29 | 30 | void writeLine([String line]) { 31 | clearLine(); 32 | if (line != null) stdout.write(line); 33 | } 34 | 35 | bool get _allowAnsi => 36 | !Platform.isWindows && stdioType(stdout) == StdioType.terminal; 37 | 38 | String _ansi(String special, [String fallback = '']) => 39 | _allowAnsi ? special : fallback; 40 | -------------------------------------------------------------------------------- /tool/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: tool 2 | publish_to: none 3 | environment: 4 | sdk: '>2.11.0 <3.0.0' 5 | dependencies: 6 | args: ^1.6.0 7 | charcode: ^1.1.3 8 | glob: ^1.2.0 9 | image: ^2.1.19 10 | markdown: ^2.1.3 11 | mime_type: ^0.3.0 12 | mustache_template: ^1.0.0 13 | path: ^1.7.0 14 | pool: ^1.4.0 15 | sass: ^1.26.5 16 | shelf: ^0.7.5 17 | string_scanner: ^1.0.5 18 | -------------------------------------------------------------------------------- /util/intellij/chap04_read.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/chap05_scanning.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/chap06_representing.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/chap07_parsing.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/chap08_evaluating.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/chap09_statements.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/chap10_control.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/chap11_functions.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/chap12_resolving.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/chap13_classes.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/chap14_inheritance.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/intellij.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/jlox.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/intellij/section_test.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /util/intellij/snippet_test.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /util/java.make: -------------------------------------------------------------------------------- 1 | # Makefile for building a single directory of Java source files. It requires 2 | # a DIR variable to be set. 3 | 4 | BUILD_DIR := build 5 | 6 | SOURCES := $(wildcard $(DIR)/com/craftinginterpreters/$(PACKAGE)/*.java) 7 | CLASSES := $(addprefix $(BUILD_DIR)/, $(SOURCES:.java=.class)) 8 | 9 | JAVA_OPTIONS := -Werror 10 | 11 | default: $(CLASSES) 12 | @: # Don't show "Nothing to be done" output. 13 | 14 | # Compile a single .java file to .class. 15 | $(BUILD_DIR)/$(DIR)/%.class: $(DIR)/%.java 16 | @ mkdir -p $(BUILD_DIR)/$(DIR) 17 | @ javac -cp $(DIR) -d $(BUILD_DIR)/$(DIR) $(JAVA_OPTIONS) -implicit:none $< 18 | @ printf "%8s %-60s %s\n" javac $< "$(JAVA_OPTIONS)" 19 | 20 | .PHONY: default 21 | --------------------------------------------------------------------------------