Repository: munificent/craftinginterpreters Branch: master Commit: 4a840f70f69c Files: 548 Total size: 4.5 MB Directory structure: gitextract_s3p1_s2h/ ├── .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/ │ │ │ ├── 1.md │ │ │ ├── 2/ │ │ │ │ ├── Hello.java │ │ │ │ └── Makefile │ │ │ └── 3/ │ │ │ ├── Makefile │ │ │ ├── linked_list │ │ │ ├── linked_list.c │ │ │ └── linked_list.xcodeproj/ │ │ │ ├── project.pbxproj │ │ │ └── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ ├── 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 │ ├── compiling-expressions.html │ ├── contents.html │ ├── control-flow.html │ ├── dedication.html │ ├── evaluating-expressions.html │ ├── functions.html │ ├── garbage-collection.html │ ├── global-variables.html │ ├── hash-tables.html │ ├── index.css │ ├── index.html │ ├── inheritance.html │ ├── introduction.html │ ├── jumping-back-and-forth.html │ ├── local-variables.html │ ├── methods-and-initializers.html │ ├── optimization.html │ ├── parsing-expressions.html │ ├── representing-code.html │ ├── resolving-and-binding.html │ ├── scanning-on-demand.html │ ├── scanning.html │ ├── script.js │ ├── statements-and-state.html │ ├── strings.html │ ├── style.css │ ├── 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/ │ │ ├── arguments.lox │ │ ├── call_init_early_return.lox │ │ ├── call_init_explicitly.lox │ │ ├── default.lox │ │ ├── default_arguments.lox │ │ ├── early_return.lox │ │ ├── extra_arguments.lox │ │ ├── init_not_method.lox │ │ ├── missing_arguments.lox │ │ ├── return_in_nested_function.lox │ │ └── return_value.lox │ ├── 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.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 ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Intermediate and built stuff. .sass-cache/ /build/ /gen/ clox *.class exercises/chapter01_introduction/3/linked_list .idea/ # I keep a scratch file at the top level to try stuff out. temp.lox # XCode user-specific stuff. xcuserdata/ # Dart stuff. /tool/.dart_tool/ /tool/.packages ================================================ FILE: LICENSE ================================================ Copyright (c) 2015 Robert Nystrom ---------------------------------- Commentary ---------------------------------- The licensing story for this repository is a little complex. Here's my motivation: * I want you to get as much use out of the material here as possible. I wrote this book to help you, and I don't want you to be encumbered when it comes to making the most of it. That's also why I put it online for free. * With my previous book, collaboration on GitHub was immesensely helpful. I want to ensure people can fork the repo, send me fixes, etc. without violating the license or feeling weird. * When it comes to code, I'm completely comfortable with people redistributing, remixing, changing, whatever with it. I've been using the MIT license for open source stuff for decades. This book contains two complete interpreters and I would be delighted for them to be the jumping-off point for any number of real full-featured language implementations. * When it comes to my prose, illustrations, and the visual design of the site, that feels a little more, I don't know, *me* than the code. The words are in my voice, the drawings are literally my handwriting, and the look of the site is part of the book's and, by extension, my brand. I feel weird thinking about someone, say taking one of the chapters and making significant changes to it to fit their writing style while still having some of it read like it came from me. Likewise, I'd be sad to see another site online that looked exactly like mine because it reuses my stylesheets. * My previous book ended up being translated into several languages. I want to be careful to not be so permissive that it prevents me from signing typical contracts that give them exclusive translation rights to certain territories and languages. * If I allow the prose and illustrations to be redistributed commercially, there is nothing preventing someone from slapping together a cheap print or ebook version of the book and putting it up for sale. I'm not too worried about my own sales being undercut, but I very much want to avoid readers finding themselves with a low quality book that they incorrectly think is from me. I worked very hard on this book. I want you to get the best possible experience. All of this is way more complex than I'd like, especially since my brain isn't wired to care about intellectual property. I like thinking about making stuff, not thinking about the legal rights around the stuff I made. (If your brain is wired to think about legal stuff and you see that I'm doing something dumb, please do let me know.) The best solution I've been able to come up with is to use two licenses: ---------------------------------- License(s) ---------------------------------- Each file in this repository falls under one of two licenses. Files whose extension is ".c", ".dart", ".h", ".java", or ".lox" use the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. All other files, including (but not limited to) ".md" (except for "book/appendix-i.md" which uses the MIT license above), ".png", ".jpg", ".html", ".scss", ".css", and ".txt" use this Creative Commons license: Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0) https://creativecommons.org/licenses/by-nc-nd/4.0/ ================================================ FILE: Makefile ================================================ BUILD_DIR := build TOOL_SOURCES := tool/pubspec.lock $(shell find tool -name '*.dart') BUILD_SNAPSHOT := $(BUILD_DIR)/build.dart.snapshot TEST_SNAPSHOT := $(BUILD_DIR)/test.dart.snapshot default: book clox jlox # Run dart pub get on tool directory. get: @ cd ./tool; dart pub get # Remove all build outputs and intermediate files. clean: @ rm -rf $(BUILD_DIR) @ rm -rf gen # Build the site. book: $(BUILD_SNAPSHOT) @ dart $(BUILD_SNAPSHOT) # Run a local development server for the site that rebuilds automatically. serve: $(BUILD_SNAPSHOT) @ dart $(BUILD_SNAPSHOT) --serve $(BUILD_SNAPSHOT): $(TOOL_SOURCES) @ mkdir -p build @ echo "Compiling Dart snapshot..." @ dart --snapshot=$@ --snapshot-kind=app-jit tool/bin/build.dart >/dev/null # Run the tests for the final versions of clox and jlox. test: debug jlox $(TEST_SNAPSHOT) @- dart $(TEST_SNAPSHOT) clox @ dart $(TEST_SNAPSHOT) jlox # Run the tests for the final version of clox. test_clox: debug $(TEST_SNAPSHOT) @ dart $(TEST_SNAPSHOT) clox # Run the tests for the final version of jlox. test_jlox: jlox $(TEST_SNAPSHOT) @ dart $(TEST_SNAPSHOT) jlox # Run the tests for every chapter's version of clox. test_c: debug c_chapters $(TEST_SNAPSHOT) @ dart $(TEST_SNAPSHOT) c # Run the tests for every chapter's version of jlox. test_java: jlox java_chapters $(TEST_SNAPSHOT) @ dart $(TEST_SNAPSHOT) java # Run the tests for every chapter's version of clox and jlox. test_all: debug jlox c_chapters java_chapters compile_snippets $(TEST_SNAPSHOT) @ dart $(TEST_SNAPSHOT) all $(TEST_SNAPSHOT): $(TOOL_SOURCES) @ mkdir -p build @ echo "Compiling Dart snapshot..." @ dart --snapshot=$@ --snapshot-kind=app-jit tool/bin/test.dart clox >/dev/null # Compile a debug build of clox. debug: @ $(MAKE) -f util/c.make NAME=cloxd MODE=debug SOURCE_DIR=c # Compile the C interpreter. clox: @ $(MAKE) -f util/c.make NAME=clox MODE=release SOURCE_DIR=c @ cp build/clox clox # For convenience, copy the interpreter to the top level. # Compile the C interpreter as ANSI standard C++. cpplox: @ $(MAKE) -f util/c.make NAME=cpplox MODE=debug CPP=true SOURCE_DIR=c # Compile and run the AST generator. generate_ast: @ $(MAKE) -f util/java.make DIR=java PACKAGE=tool @ java -cp build/java com.craftinginterpreters.tool.GenerateAst \ java/com/craftinginterpreters/lox # Compile the Java interpreter .java files to .class files. jlox: generate_ast @ $(MAKE) -f util/java.make DIR=java PACKAGE=lox run_generate_ast = @ java -cp build/gen/$(1) \ com.craftinginterpreters.tool.GenerateAst \ gen/$(1)/com/craftinginterpreters/lox java_chapters: split_chapters @ $(MAKE) -f util/java.make DIR=gen/chap04_scanning PACKAGE=lox @ $(MAKE) -f util/java.make DIR=gen/chap05_representing PACKAGE=tool $(call run_generate_ast,chap05_representing) @ $(MAKE) -f util/java.make DIR=gen/chap05_representing PACKAGE=lox @ $(MAKE) -f util/java.make DIR=gen/chap06_parsing PACKAGE=tool $(call run_generate_ast,chap06_parsing) @ $(MAKE) -f util/java.make DIR=gen/chap06_parsing PACKAGE=lox @ $(MAKE) -f util/java.make DIR=gen/chap07_evaluating PACKAGE=tool $(call run_generate_ast,chap07_evaluating) @ $(MAKE) -f util/java.make DIR=gen/chap07_evaluating PACKAGE=lox @ $(MAKE) -f util/java.make DIR=gen/chap08_statements PACKAGE=tool $(call run_generate_ast,chap08_statements) @ $(MAKE) -f util/java.make DIR=gen/chap08_statements PACKAGE=lox @ $(MAKE) -f util/java.make DIR=gen/chap09_control PACKAGE=tool $(call run_generate_ast,chap09_control) @ $(MAKE) -f util/java.make DIR=gen/chap09_control PACKAGE=lox @ $(MAKE) -f util/java.make DIR=gen/chap10_functions PACKAGE=tool $(call run_generate_ast,chap10_functions) @ $(MAKE) -f util/java.make DIR=gen/chap10_functions PACKAGE=lox @ $(MAKE) -f util/java.make DIR=gen/chap11_resolving PACKAGE=tool $(call run_generate_ast,chap11_resolving) @ $(MAKE) -f util/java.make DIR=gen/chap11_resolving PACKAGE=lox @ $(MAKE) -f util/java.make DIR=gen/chap12_classes PACKAGE=tool $(call run_generate_ast,chap12_classes) @ $(MAKE) -f util/java.make DIR=gen/chap12_classes PACKAGE=lox @ $(MAKE) -f util/java.make DIR=gen/chap13_inheritance PACKAGE=tool $(call run_generate_ast,chap13_inheritance) @ $(MAKE) -f util/java.make DIR=gen/chap13_inheritance PACKAGE=lox c_chapters: split_chapters @ $(MAKE) -f util/c.make NAME=chap14_chunks MODE=release SOURCE_DIR=gen/chap14_chunks @ $(MAKE) -f util/c.make NAME=chap15_virtual MODE=release SOURCE_DIR=gen/chap15_virtual @ $(MAKE) -f util/c.make NAME=chap16_scanning MODE=release SOURCE_DIR=gen/chap16_scanning @ $(MAKE) -f util/c.make NAME=chap17_compiling MODE=release SOURCE_DIR=gen/chap17_compiling @ $(MAKE) -f util/c.make NAME=chap18_types MODE=release SOURCE_DIR=gen/chap18_types @ $(MAKE) -f util/c.make NAME=chap19_strings MODE=release SOURCE_DIR=gen/chap19_strings @ $(MAKE) -f util/c.make NAME=chap20_hash MODE=release SOURCE_DIR=gen/chap20_hash @ $(MAKE) -f util/c.make NAME=chap21_global MODE=release SOURCE_DIR=gen/chap21_global @ $(MAKE) -f util/c.make NAME=chap22_local MODE=release SOURCE_DIR=gen/chap22_local @ $(MAKE) -f util/c.make NAME=chap23_jumping MODE=release SOURCE_DIR=gen/chap23_jumping @ $(MAKE) -f util/c.make NAME=chap24_calls MODE=release SOURCE_DIR=gen/chap24_calls @ $(MAKE) -f util/c.make NAME=chap25_closures MODE=release SOURCE_DIR=gen/chap25_closures @ $(MAKE) -f util/c.make NAME=chap26_garbage MODE=release SOURCE_DIR=gen/chap26_garbage @ $(MAKE) -f util/c.make NAME=chap27_classes MODE=release SOURCE_DIR=gen/chap27_classes @ $(MAKE) -f util/c.make NAME=chap28_methods MODE=release SOURCE_DIR=gen/chap28_methods @ $(MAKE) -f util/c.make NAME=chap29_superclasses MODE=release SOURCE_DIR=gen/chap29_superclasses @ $(MAKE) -f util/c.make NAME=chap30_optimization MODE=release SOURCE_DIR=gen/chap30_optimization cpp_chapters: split_chapters @ $(MAKE) -f util/c.make NAME=cpp_chap14_chunks MODE=release CPP=true SOURCE_DIR=gen/chap14_chunks @ $(MAKE) -f util/c.make NAME=cpp_chap15_virtual MODE=release CPP=true SOURCE_DIR=gen/chap15_virtual @ $(MAKE) -f util/c.make NAME=cpp_chap16_scanning MODE=release CPP=true SOURCE_DIR=gen/chap16_scanning @ $(MAKE) -f util/c.make NAME=cpp_chap17_compiling MODE=release CPP=true SOURCE_DIR=gen/chap17_compiling @ $(MAKE) -f util/c.make NAME=cpp_chap18_types MODE=release CPP=true SOURCE_DIR=gen/chap18_types @ $(MAKE) -f util/c.make NAME=cpp_chap19_strings MODE=release CPP=true SOURCE_DIR=gen/chap19_strings @ $(MAKE) -f util/c.make NAME=cpp_chap20_hash MODE=release CPP=true SOURCE_DIR=gen/chap20_hash @ $(MAKE) -f util/c.make NAME=cpp_chap21_global MODE=release CPP=true SOURCE_DIR=gen/chap21_global @ $(MAKE) -f util/c.make NAME=cpp_chap22_local MODE=release CPP=true SOURCE_DIR=gen/chap22_local @ $(MAKE) -f util/c.make NAME=cpp_chap23_jumping MODE=release CPP=true SOURCE_DIR=gen/chap23_jumping @ $(MAKE) -f util/c.make NAME=cpp_chap24_calls MODE=release CPP=true SOURCE_DIR=gen/chap24_calls @ $(MAKE) -f util/c.make NAME=cpp_chap25_closures MODE=release CPP=true SOURCE_DIR=gen/chap25_closures @ $(MAKE) -f util/c.make NAME=cpp_chap26_garbage MODE=release CPP=true SOURCE_DIR=gen/chap26_garbage @ $(MAKE) -f util/c.make NAME=cpp_chap27_classes MODE=release CPP=true SOURCE_DIR=gen/chap27_classes @ $(MAKE) -f util/c.make NAME=cpp_chap28_methods MODE=release CPP=true SOURCE_DIR=gen/chap28_methods @ $(MAKE) -f util/c.make NAME=cpp_chap29_superclasses MODE=release CPP=true SOURCE_DIR=gen/chap29_superclasses @ $(MAKE) -f util/c.make NAME=cpp_chap30_optimization MODE=release CPP=true SOURCE_DIR=gen/chap30_optimization diffs: split_chapters java_chapters @ mkdir -p build/diffs @ -diff --recursive --new-file nonexistent/ gen/chap04_scanning/com/craftinginterpreters/ > build/diffs/chap04_scanning.diff @ -diff --recursive --new-file gen/chap04_scanning/com/craftinginterpreters/ gen/chap05_representing/com/craftinginterpreters/ > build/diffs/chap05_representing.diff @ -diff --recursive --new-file gen/chap05_representing/com/craftinginterpreters/ gen/chap06_parsing/com/craftinginterpreters/ > build/diffs/chap06_parsing.diff @ -diff --recursive --new-file gen/chap06_parsing/com/craftinginterpreters/ gen/chap07_evaluating/com/craftinginterpreters/ > build/diffs/chap07_evaluating.diff @ -diff --recursive --new-file gen/chap07_evaluating/com/craftinginterpreters/ gen/chap08_statements/com/craftinginterpreters/ > build/diffs/chap08_statements.diff @ -diff --recursive --new-file gen/chap08_statements/com/craftinginterpreters/ gen/chap09_control/com/craftinginterpreters/ > build/diffs/chap09_control.diff @ -diff --recursive --new-file gen/chap09_control/com/craftinginterpreters/ gen/chap10_functions/com/craftinginterpreters/ > build/diffs/chap10_functions.diff @ -diff --recursive --new-file gen/chap10_functions/com/craftinginterpreters/ gen/chap11_resolving/com/craftinginterpreters/ > build/diffs/chap11_resolving.diff @ -diff --recursive --new-file gen/chap11_resolving/com/craftinginterpreters/ gen/chap12_classes/com/craftinginterpreters/ > build/diffs/chap12_classes.diff @ -diff --recursive --new-file gen/chap12_classes/com/craftinginterpreters/ gen/chap13_inheritance/com/craftinginterpreters/ > build/diffs/chap13_inheritance.diff @ -diff --new-file nonexistent/ gen/chap14_chunks/ > build/diffs/chap14_chunks.diff @ -diff --new-file gen/chap14_chunks/ gen/chap15_virtual/ > build/diffs/chap15_virtual.diff @ -diff --new-file gen/chap15_virtual/ gen/chap16_scanning/ > build/diffs/chap16_scanning.diff @ -diff --new-file gen/chap16_scanning/ gen/chap17_compiling/ > build/diffs/chap17_compiling.diff @ -diff --new-file gen/chap17_compiling/ gen/chap18_types/ > build/diffs/chap18_types.diff @ -diff --new-file gen/chap18_types/ gen/chap19_strings/ > build/diffs/chap19_strings.diff @ -diff --new-file gen/chap19_strings/ gen/chap20_hash/ > build/diffs/chap20_hash.diff @ -diff --new-file gen/chap20_hash/ gen/chap21_global/ > build/diffs/chap21_global.diff @ -diff --new-file gen/chap21_global/ gen/chap22_local/ > build/diffs/chap22_local.diff @ -diff --new-file gen/chap22_local/ gen/chap23_jumping/ > build/diffs/chap23_jumping.diff @ -diff --new-file gen/chap23_jumping/ gen/chap24_calls/ > build/diffs/chap24_calls.diff @ -diff --new-file gen/chap24_calls/ gen/chap25_closures/ > build/diffs/chap25_closures.diff @ -diff --new-file gen/chap25_closures/ gen/chap26_garbage/ > build/diffs/chap26_garbage.diff @ -diff --new-file gen/chap26_garbage/ gen/chap27_classes/ > build/diffs/chap27_classes.diff @ -diff --new-file gen/chap27_classes/ gen/chap28_methods/ > build/diffs/chap28_methods.diff @ -diff --new-file gen/chap28_methods/ gen/chap29_superclasses/ > build/diffs/chap29_superclasses.diff @ -diff --new-file gen/chap29_superclasses/ gen/chap30_optimization/ > build/diffs/chap30_optimization.diff split_chapters: @ dart tool/bin/split_chapters.dart compile_snippets: @ dart tool/bin/compile_snippets.dart # Generate the XML for importing into InDesign. xml: $(TOOL_SOURCES) @ dart --enable-asserts tool/bin/build_xml.dart .PHONY: book c_chapters clean clox compile_snippets debug default diffs \ get java_chapters jlox serve split_chapters test test_all test_c test_java ================================================ FILE: README.md ================================================ This is the repo used for the in-progress book "[Crafting Interpreters][]". It contains the Markdown text of the book, full implementations of both interpreters, as well as the build system to weave the two together into the final site. [crafting interpreters]: http://craftinginterpreters.com If you find an error or have a suggestion, please do file an issue here. Thank you! ## Contributing One of the absolute best things about writing a book online and putting it out there before it's done is that people like you have been kind enough to give me feedback, point out typos, and find other errors or unclear text. If you'd like to do that, great! You can just file bugs here on the repo, or send a pull request if you're so inclined. If you want to send a pull request, but don't want to get the build system set up to regenerate the HTML too, don't worry about it. I'll do that when I pull it in. ## Ports and implementations Another way to get involved is by sharing your own implementation of Lox. Ports to other languages are particularly useful since not every reader likes Java and C. Feel free to add your Lox port or implementation to the wiki: * [Lox implementations][] [lox implementations]: https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations ## Building Stuff I am a terribly forgetful, error-prone mammal, so I automated as much as I could. ### Prerequisites I develop on an OS X machine, but any POSIX system should work too. With a little extra effort, you should be able to get this working on Windows as well, though I can't help you out much. Most of the work is orchestrated by make. The build scripts, test runner, and other utilities are all written in [Dart][]. Instructions to install Dart are [here][install]. Once you have Dart installed and on your path, run: ```sh $ make get ``` [dart]: https://dart.dev/ [install]: https://dart.dev/get-dart This downloads all of the packages used by the build and test scripts. In order to compile the two interpreters, you also need a C compiler on your path as well as `javac`. ### Building Once you've got that setup, try: ```sh $ make ``` If everything is working, that will generate the site for the book as well as compiling the two interpreters clox and jlox. You can run either interpreter right from the root of the repo: ```sh $ ./clox $ ./jlox ``` ### Hacking on the book The Markdown and snippets of source code are woven together into the final HTML using a hand-written static site generator that started out as a [single tiny Python script][py] for [my first book][gpp] and somehow grew into something approximating a real program. [py]: https://github.com/munificent/game-programming-patterns/blob/master/script/format.py [gpp]: http://gameprogrammingpatterns.com/ The generated HTML is committed in the repo under `site/`. It is built from a combination of Markdown for prose, which lives in `book/`, and snippets of code that are weaved in from the Java and C implementations in `java/` and `c/`. (All of those funny looking comments in the source code are how it knows which snippet goes where.) The script that does all the magic is `tool/bin/build.dart`. You can run that directly, or run: ```sh $ make book ``` That generates the entire site in one batch. If you are incrementally working on it, you'll want to run the development server: ```sh $ make serve ``` This runs a little HTTP server on localhost rooted at the `site/` directory. Any time you request a page, it regenerates any files whose sources have been changed, including Markdown files, interpreter source files, templates, and assets. Just let that keep running, edit files locally, and refresh your browser to see the changes. ### Building the interpreters You can build each interpreter like so: ```sh $ make clox $ make jlox ``` This builds the final version of each interpreter as it appears at the end of its part in the book. You can also see what the interpreters look like at the end of each chapter. (I use this to make sure they are working even in the middle of the book.) This is driven by a script, `tool/bin/split_chapters.dart` that uses the same comment markers for the code snippets to determine which chunks of code are present in each chapter. It takes only the snippets that have been seen by the end of each chapter and produces a new copy of the source in `gen/`, one directory for each chapter's code. (These are also an easier way to view the source code since they have all of the distracting marker comments stripped out.) Then, each of those can be built separately. Run: ```sh $ make c_chapters ``` And in the `build/` directory, you'll get an executable for each chapter, like `chap14_chunks`, etc. Likewise: ```sh $ make java_chapters ``` This compiles the Java code to classfiles in `build/gen/` in a subdirectory for each chapter. ## Testing I have a full Lox test suite that I use to ensure the interpreters in the book do what they're supposed to do. The test cases live in `test/`. The Dart program `tool/bin/test.dart` is a test runner that runs each of those test files on a Lox interpreter, parses the result, and validates that that the test does what it's expected to do. There are various interpreters you can run the tests against: ```sh $ make test # The final versions of clox and jlox. $ make test_clox # The final version of clox. $ make test_jlox # The final version of jlox. $ make test_c # Every chapter's version of clox. $ make test_java # Every chapter's version of jlox. $ make test_all # All of the above. ``` ### Testing your implementation You are welcome to use the test suite and the test runner to test your own Lox implementation. The test runner is at `tool/bin/test.dart` and can be given a custom interpreter executable to run using `--interpreter`. For example, if you had an interpreter executable at `my_code/boblox`, you could test it like: ```sh $ dart tool/bin/test.dart clox --interpreter my_code/boblox ``` You still need to tell it which suite of tests to run because that determines the test expectations. If your interpreter should behave like jlox, use "jlox" as the suite name. If it behaves like clox, use "clox". If your interpreter is only complete up to the end of one of the chapters in the book, you can use that chapter as the suite, like "chap10_functions". See the Makefile for the names of all of the chapters. If your interpreter needs other command line arguments passed to use, pass them to the test runner using `--arguments` and it will forward to your interpreter. ## Repository Layout * `asset/` – Sass files and jinja2 templates used to generate the site. * `book/` - Markdown files for the text of each chapter. * `build/` - Intermediate files and other build output (except for the site itself) go here. Not committed to Git. * `c/` – Source code of clox, the interpreter written in C. Also contains an XCode project, if that's your thing. * `gen/` – Java source files generated by GenerateAst.java go here. Not committed. * `java/` – Source code of jlox, the interpreter written in Java. * `note/` – Various research, notes, TODOs, and other miscellanea. * `note/answers` – Sample answers for the challenges. No cheating! * `site/` – The final generated site. The contents of this directory directly mirror craftinginterpreters.com. Most content here is generated by build.py, but fonts, images, and JS only live here. Everything is committed, even the generated content. * `test/` – Test cases for the Lox implementations. * `tool/` – Dart package containing the build, test, and other scripts. ================================================ FILE: asset/index.scss ================================================ @import 'sass/shared'; @import 'sass/sign-up'; body, h1, h2, h3, h4, p, blockquote, code, ul, ol, dl, dd, img { margin: 0; } body { background: $dark url('image/background.png') top center / 100% auto no-repeat; color: #222; font: normal 16px/24px $serif; } a { color: $primary; text-decoration: none; border-bottom: solid 1px transparentize($light, 1.0); transition: color 0.2s ease, border-color 0.4s ease; } a:hover { color: $primary; border-bottom: solid 1px opacify($light, 1.0); } article { margin: 0 auto; padding: 0 0 12px 0; max-width: $col * 20; background: #fff; } header { margin: 0 0 $col 0; color: $warm-dark; background: $warm-5; border-bottom: solid 1px $warm-4; } main { margin: 0 $col; } img.header { display: block; width: 100%; } img.small { display: none; } div.intro { display: flex; blockquote { flex-basis: 40%; margin: 0 $col 0 0; font: italic 28px/42px $serif; } div.text { flex-basis: 60%; margin: 8px 0 24px 0; } } p + p { margin-top: 24px; } .format { margin: 0 -12px 24px -12px; padding: 12px 12px 8px 12px; height: 244px; box-sizing: border-box; background: $lighter; background-size: cover; background-position: left; color: #444; border-radius: 3px; font: normal 16px/24px $nav; h3 { margin: 0; padding: 0 0 4px 0; font: 600 16px/24px $nav; text-transform: uppercase; letter-spacing: 1px; } p { margin-bottom: 8px; } } .format.print, .format.pdf { background-position: right; text-align: right; } .format-info { display: inline-block; width: $col * 8; text-align: left; table { width: 100%; border-collapse: collapse; td + td { padding-left: 5px; } } } .format.print { background-image: url("image/format-print.jpg"); } .format.ebook { background-image: url("image/format-ebook.jpg"); } .format.pdf { background-image: url("image/format-pdf.jpg"); } .format.web { background-image: url("image/format-web.jpg"); } a.action { display: block; margin: 0 0 4px 0; padding: 4px 0; text-align: center; border-radius: 3px; background: $primary; transition: background-color 0.2s ease, color 0.2s ease; font: 400 17px/24px $nav; color: white; small { font-size: 14px; padding: 4px; color: hsla(0, 0, 100%, 0.7); transition: color 0.2s ease; } } a.action:hover { background-color: hsl(200, 85%, 55%); small { color: white; } } h3 { font: italic 24px/24px $serif; margin: 12px 0; } img.author { float: left; width: 240px; margin: 0 12px 0 -12px; padding: 12px; background: $warm-5; border-radius: 3px; } div.author { vertical-align: top; margin: 36px 0 0 240px + $col; } footer { position: relative; border-top: solid 1px $light; color: $gray-4; font: 400 15px $nav; text-align: center; margin: 12px 0 36px 0; padding-top: 48px; a, a:hover { border: none; } } @media only screen and (max-width: 700px) { main { margin: 0 24px; } header { margin-bottom: 24px; } img.big { display: none; } img.small { display: block; } div.intro { display: block; blockquote { display: block; font: italic 24px/36px $serif; } div.text { display: block; margin: 24px 0 24px 0; } } .format { margin-bottom: 12px; height: auto; background-blend-mode: lighten; } .format-info { display: block; width: 100%; } .format.print { background-color: #a6a29f; } .format.ebook { background-color: #97a2aa; } .format.pdf { background-color: #cfccca; } .format.web { background-color: #d6dbd3; } img.author { float: none; } div.author { margin: 0 0 0 0; } } ================================================ FILE: asset/mustache/contents-nav.html ================================================