-
Notifications
You must be signed in to change notification settings - Fork 120
CS1729 Assignment 1
Your first assignment has three parts:
- Compile a portion of core Pyret to JavaScript,
- Implement a portion of the Pyret runtime in JavaScript,
- Enable pausing and breaking for the compiled code.
You can work in pairs or solo for CS1729, tell me by the end of the day Monday if you're planning on working alone or with a partner.
You should fork the pyret-lang repo on Github and do all your work on your own fork. If we have contributions from one another that we want to share, we'll incorporate them into the main Pyret repo and then distribute them from there.
The Pyret repository has a directory called js/ that contains the files and support code you'll need for this assignment (and CS1729 in general):
-
runtime.js--- Your JavaScript implementation of Pyret's runtime. It corresponds to the filesrc/lang/runtime.rkt, and will hold your representation of Pyret values, and built-in functions and methods for accessing fields, updating objects, doing primitive arithmetic and string manipulation, etc. It is seeded with a naive representation of numbers, methods, and functions to show one simple approach to the problem. -
pyret-to-js.arr--- Your Pyret implementation of a Pyret-to-JavaScript compiler. The main entry point isprogram-to-js(ast :: Program) -> String, which converts a parsed Pyret program to a string of JavaScript code. You will also be completing this implementation, which starts with a naive compilation for numbers, blocks, and application.You will need to refer to the definition of the Pyret AST in
src/lang/racket-ffi/ast.arr. This is the complete Pyret surface grammar. For now, you only need to support a smaller subset of this (the post-desugaring subset of the language), which is documented below. -
create-tests.arr--- A script that generates test files to run unit tests on your compiler. It outputs the tests intotest-runner/tests.jsas a JavaScript program that creates aTESTSdatastructure. See the end of the file for example tests. You can run this to re-generate your tests usingraco pyret --no-checks create-tests.arrThis is probably the most convenient place to add your own tests, but you're free to come up with other ways and extend this framework; it is functional but minimal.
-
test-runner/test-support.js--- This contains JavaScript support for running tests. This is where you can write JavaScript functions to use as predicates on the result of running compiled Pyret programs. Two are defined ---pyretEqualsandisNumber--- you will probably want to write more predicates. -
test-runner/test.html--- You shouldn't need to edit this file, it contains the test runner that usestests.jsandtest-support.jsto run your unit tests.
Pyret goes through a desugaring phase before reaching core Pyret, which is the language you must compile to JavaScript. As a result, the set of forms you need to handle is much smaller than the entire data definition in ast.arr. You must compile these forms:
-
s_block(l :: Loc, stmts :: List<Expr>)--- A block of expressions as statements that get their own scope -
s_user_block(l :: Loc, body :: Expr)--- Compiles identically tos_block, indicates that a user used theblock:form (rather than an implicit block for a function body, etc.) -
s_var(l :: Loc, name :: Bind, value :: Expr)--- Note that the desugaring process also checks well-formedness, so you can assume that only variables are used ins_assignexpressions. s_let(l :: Loc, name :: Bind, value :: Expr)s_assign(l :: Loc, id :: String, value :: Expr)s_if_else(l :: Loc, branches :: List<IfBranch>, _else :: Expr)-
s_try(l :: Loc, body :: Expr, id :: Bind, _except :: Expr)--- Pyret's semantics for try/catch is modelled nicely by JavaScript's try/catch. -
s_lam(l :: Loc, params :: List<String>, args :: List<Bind>, ann :: Ann, doc :: String, body :: Expr, check :: Expr)--- You don't need to worry about anything to do with types/annotations or check blocks. These are completely handled by desugaring and annotation checking before arriving at core Pyret. s_method(l :: Loc, args :: List<Bind>, ann :: Ann, doc :: String, body :: Expr, check :: Expr)-
s_extend(l :: Loc, super :: Expr, fields :: List<Member>)--- This is the expression form forobj.{field1: val1, ...} -
s_update(l :: Loc, super :: Expr, fields :: List<Member>)--- This is the expression form forobj!{field1: val1, ...} s_obj(l :: Loc, fields :: List<Member>)s_app(l :: Loc, _fun :: Expr, args :: List<Expr>)-
s_id(l :: Loc, id :: String)--- You should think carefully about your representation of identifiers that come from your JavaScript implemented runtime. s_num(l :: Loc, n :: Number)s_bool(l :: Loc, b :: Bool)s_str(l :: Loc, s :: String)-
s_bracket(l :: Loc, obj :: Expr, field :: Expr)--- Important: You can assume for now thatfieldis always ans_str. We'll get to hash tables and computed-string lookup later on. -
s_colon_bracket(l :: Loc, obj :: Expr, field :: Expr)--- Important: You can assume for now thatfieldis always ans_str. We'll get to hash tables and computed-string lookup later on. -
s_get_bang(l :: Loc, obj :: Expr, field :: String)--- Corresponds toobj!xexpressions