Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • S sweet-core
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 62
    • Issues 62
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 4
    • Merge requests 4
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • sweet-js
  • sweet-core
  • Wiki
  • expander design

expander design · Changes

Page history
Created expander design (markdown) authored Apr 29, 2013 by disnet's avatar disnet
Show whitespace changes
Inline Side-by-side
expander-design.md 0 → 100644
View page @ b4fab113
# Sweet.js
## Core Structures
The main data types are `Syntax` and `TermTree`:
Syntax :: {
token :: Token,
context :: Context,
mark :: (Int?) -> Syntax
rename :: (Syntax or [Syntax], Str) -> Syntax
push_dummy_rename :: (Str) -> Syntax
swap_dummy_rename :: (Syntax, Str, Str) -> Syntax
}
The `Syntax` object holds the token (a holdover data structure from esprima which knows about the token's value and line numbers) and its context (a structure of marks and renames used for hygiene) along with a couple of methods to help with hygiene.
Each `Syntax` object is in one-to-one correlation with an individual token.
In contrast, the `TermTree` object holds a collection of of `Syntax` objects in a closer and closer approximation of the final AST.
TermTree :: {
destruct :: () -> [Syntax]
}
It's basically an AST, just not as complete as the final AST generated by esprima. Productions in the grammar then are represented by individual term trees:
BinOp extends TermTree :: {
left :: TermTree
op :: TermTree
right :: TermTree
}
## expand
The main entry point into the expander is, appropriately enough, `expand`:
expand :: ([Syntax], Map, Map) -> [TermTree]
function expand(toks, env, ctx) { ... }
The `expand` function is primarily responsible for handling hygiene. Most of its work happens when dealing with functions (renaming all the parameters and whatnot). The `env` param is a mapping from identifiers to macro definitions and `ctx` is a mapping of names to names (used for hygiene).
The `expand` function delegates to two sub expand like functions:
expandToTermTree :: ([Syntax], Map) -> {terms: [TermTree], env: Map}
Responsible for converting the syntax to TermTrees and loading any macro definitions it finds into the new `env` map.
expandTermTreeToFinal :: (TermTree, Map, Map) -> TermTree
Responsible for packing each term tree into its final state. This means recursively expanding sub trees and handling various hygiene tasks.
These are roughly analogous to `parse1` and `parse2` in the honu paper.
## enforest
The `enforest` function deals with transforming `Syntax` objects to a `TermTree`:
enforest :: ([Syntax], Map) -> {
result :: TermTree
rest :: [Syntax]
}
# Honu
The main contracts for honu:
parse :: ([Syntax], Env) -> AST
parse1 :: ([Syntax], Env) -> ([TermTree], Env)
parse2 :: ([TermTree], Env) -> AST
enforest :: ([Syntax], Env) -> (TermTree, [Syntax])
data TermTree = Macro Str [Syntax]
| Expr [TermTree]
| Bop TermTree Str TermTree
| Fun Str [TermTree] [Syntax]
| Block [Syntax]
| Id Syntax
| Lit Syntax
| Call [TermTree] [TermTree]
Some partial pattern matching definitions in a haskelly notation:
parse :: ([Syntax], Env) -> AST
parse stx env = let (terms, env') = parse1 stx env
in parse2 terms env'
parse1 :: [Syntax] -> Env -> ([TermTree], Env)
parse1 [] env = ([], env)
parse1 in env =
case (enforest in env) of
(Macro n b, rest) -> parse1 rest (update n (loadm b))
(Expr e, rest) -> (Expr e) : (parse1 rest env)
-- case when var declaration (somewhat complicated)
parse2 :: [TermTree] -> Env -> AST
parse2 forms env = map parse2' forms
parse2' (Fun n vs b) env = FunAST n vs (parse b (aug env vs))
parse2' (Block b) env = BlockAST (parse b env)
parse2' (Id i) env = IdAST i
parse2' (Lit l) env = LitAST l
parse2' (Call l r) env = CallAST (parse2 l env) (parse2 r env)
parse2' (Bop l o r) env = BopAST (parse2 l env) o (parse2 r env)
And the `enforest` function itself:
data Syntax = LitR Int
| IdR Str
| BinopR Str
| ParenR [Syntax]
| ...
enforest :: [Syntax] -> Env -> (TermTree, [Syntax])
enforest (LitR n:rest) env = enforest (Lit n:rest) env
enforest (IdR i:rest) env
| lookup i env == Var id = enforest (Id id:rest) env
| lookup i env == Macro t = enforest (t rest) env
enforest (ltree:(IdR i):rest) env
| lookup i env == BopR op = case enforest rest env of
(rtree, rest) -> enforest (Bop ltree op rtree:rest) env
-- similar for uop
enforest (ltree:ParenR args:rest)
| -- each arg must enforest to have no `rest`
= enforest (Call ltree argtrees:rest) env
Clone repository
  • Example macros
  • FAQ
  • High level design overview
  • Home
  • Macro resources
  • Patterns
  • Syntax Case
  • case api
  • custom operators
  • design
  • expander design
  • modules
  • node loader
  • pattern_class
  • reader scratch
View All Pages