Skip to content

BaLiKfromUA/pylox

Repository files navigation

pylox

codecov

pylox is Python implementation of Lox programming language which is a demo language from Crafting Interpreters book by Bob Nystrom.

I'm doing this because:

  1. I want to learn about programming languages design and implementation.
  2. I don't want to just read the book or copy and paste the code from it and I want to do something else than C or Java.
  3. I want to become more "fluent" with Python and its dev infrastructure.
  4. Fun.

Features

  • Lexer
  • Parser
  • Basic types (string, boolean, number)
  • Floating point arithmetic, string concatenation
  • Conditional expressions (ternary operator ?:)
  • Logical expressions (and, or)
  • Control flow (for, while, if statements)
    • break statement
      • Check break out of loops
  • Functions
    • Check return out of function
  • Classes
    • Check this out of class
    • Check return inside constructor init
  • Inheritance

Challenges

  • Add support to Lox’s scanner for C-style /* ... */ block comments. Make sure to handle newlines in them. Consider allowing them to nest. Solution
  • Define a visitor class for our syntax tree classes that takes an expression, converts it to RPN, and returns the resulting string. Solution
  • Add support for comma expressions. Give them the same precedence and associativity as in C. Write the grammar, and then implement the necessary parsing code.
  • Add support for the C-style conditional or “ternary” operator ?:
  • Add error productions to handle each binary operator appearing without a left-hand operand. In other words, detect a binary operator appearing at the beginning of an expression. Report that as an error, but also parse and discard a right-hand operand with the appropriate precedence. Solution
  • Many languages define + such that if either operand is a string, the other is converted to a string and the results are then concatenated. For example, "scone" + 4 would yield scone4. Extend the code in visitBinaryExpr() to support that. Solution
  • What happens right now if you divide a number by zero? What do you think should happen? Justify your choice. How do other languages you know handle division by zero, and why do they make the choices they do? Change the implementation in visitBinaryExpr() to detect and report a runtime error for this case. Solution
  • Add support to the REPL to let users type in both statements and expressions. If they enter a statement, execute it. If they enter an expression, evaluate it and display the result value. Solution
  • Unlike Lox, most other C-style languages also support break and continue statements inside loops. Add support for break statements. It should be a syntax error to have a break statement appear outside of any enclosing loop. Solution
  • Languages that encourage a functional style usually support anonymous functions or lambdas—an expression syntax that creates a function without binding it to a name. Add anonymous function syntax to Lox.
  • Extend the resolver to report an error if a local variable is never used.
  • Extend the resolver to associate a unique index for each local variable declared in a scope.
  • Add support of static methods
  • Extend Lox to support getter methods.

My own design/implementation decisions

  • Support of lists. For example:
    var list = [1, 2, 3, 4, 5];
    print list[0]; // 1
    
    var result = [];
    for (var i = 0; list[i] != nil; i = i + 1) {
      result[i] = list[i] * 10;
    }
    print result; // [10, 20, 30, 40, 50]
  • Support of functional list processing. For example:
    var list = [1, 2, 3, 4, 5];
    print map(lambda(num) { return num * num; }, list); // [1, 4, 9, 16, 25]
  • Support of additional built-in functions:
    • input
    • len