Skip to content

Commit

Permalink
refactor(pointfree-lang): rename grammar rule / nodetype MAP=>OBJ, ad…
Browse files Browse the repository at this point in the history
…d docs

- rename resolveMap => resolveObject
- rename visitMap => visitObject
  • Loading branch information
postspectacular committed Apr 3, 2018
1 parent 5450e50 commit 1c899a1
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 21 deletions.
2 changes: 1 addition & 1 deletion packages/pointfree-lang/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export enum NodeType {
BOOLEAN,
STRING,
ARRAY,
MAP,
OBJ,

COMMENT,
STACK_COMMENT,
Expand Down
20 changes: 10 additions & 10 deletions packages/pointfree-lang/src/grammar.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// NodeType[NodeType["BOOLEAN"] = 7] = "BOOLEAN";
// NodeType[NodeType["STRING"] = 8] = "STRING";
// NodeType[NodeType["ARRAY"] = 9] = "ARRAY";
// NodeType[NodeType["MAP"] = 10] = "MAP";
// NodeType[NodeType["OBJ"] = 10] = "OBJ";
// NodeType[NodeType["COMMENT"] = 11] = "COMMENT";
// NodeType[NodeType["STACK_COMMENT"] = 12] = "STACK_COMMENT";

Expand All @@ -36,7 +36,7 @@ NonWordExpr
/ Var
/ Comment
/ Array
/ Map
/ Obj
/ Atom
) _ { return ast(expr); }

Expand All @@ -50,29 +50,29 @@ Array
return { type: NodeType.ARRAY, body };
}

Map
= "{" _ body:MapPair* "}" {
return { type: NodeType.MAP, body };
Obj
= "{" _ body:ObjPair* "}" {
return { type: NodeType.OBJ, body };
}

MapPair
= k:MapKey v:MapVal { return [ k, v ]; }
ObjPair
= k:ObjKey v:ObjVal { return [ k, v ]; }

MapKey
ObjKey
= k:(
String
/ Number
/ VarDeref
/ Sym
) ":" { return ast(k); }

MapVal
ObjVal
= _ val:(
Atom
/ LitQuote
/ VarDeref
/ Array
/ Map
/ Obj
) _ { return ast(val); }

Atom
Expand Down
96 changes: 86 additions & 10 deletions packages/pointfree-lang/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as pf from "@thi.ng/pointfree";
import { ASTNode, NodeType, ALIASES, VisitorState } from "./api";
import { parse, SyntaxError } from "./parser";

let DEBUG = true;
let DEBUG = false;

export const setDebug = (state: boolean) => DEBUG = state;

Expand Down Expand Up @@ -49,6 +49,13 @@ const resolveVar = (node: ASTNode, ctx: pf.StackContext) => {
return ctx[2][id];
};

/**
* Resolves given node's value. Used by `resolveArray` & `resolveObject`
* to process internal values (and in the latter case also their keys).
*
* @param node
* @param ctx
*/
const resolveNode = (node: ASTNode, ctx: pf.StackContext) => {
switch (node.type) {
case NodeType.SYM:
Expand All @@ -59,13 +66,19 @@ const resolveNode = (node: ASTNode, ctx: pf.StackContext) => {
return pf.storekey(node.id);
case NodeType.ARRAY:
return resolveArray(node, ctx);
case NodeType.MAP:
return resolveMap(node, ctx);
case NodeType.OBJ:
return resolveObject(node, ctx);
default:
return node.body;
}
};

/**
* Constructs an array literal (quotation) from given AST node.
*
* @param node
* @param ctx
*/
const resolveArray = (node: ASTNode, ctx: pf.StackContext) => {
const res = [];
for (let n of node.body) {
Expand All @@ -74,14 +87,27 @@ const resolveArray = (node: ASTNode, ctx: pf.StackContext) => {
return res;
};

const resolveMap = (node: ASTNode, ctx: pf.StackContext) => {
/**
* Constructs object literal from given AST node.
*
* @param node
* @param ctx
*/
const resolveObject = (node: ASTNode, ctx: pf.StackContext) => {
const res = {};
for (let [k, v] of node.body) {
res[k.type === NodeType.SYM ? k.id : resolveNode(k, ctx)] = resolveNode(v, ctx);
}
return res;
};

/**
* Main AST node visitor dispatcher.
*
* @param node
* @param ctx
* @param state
*/
const visit = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) => {
DEBUG && console.log("visit", NodeType[node.type], node, ctx[0].toString());
switch (node.type) {
Expand All @@ -95,8 +121,8 @@ const visit = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) => {
return ctx;
case NodeType.ARRAY:
return visitArray(node, ctx, state);
case NodeType.MAP:
return visitMap(node, ctx, state);
case NodeType.OBJ:
return visitObject(node, ctx, state);
case NodeType.VAR_DEREF:
return visitDeref(node, ctx, state);
case NodeType.VAR_STORE:
Expand All @@ -109,6 +135,15 @@ const visit = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) => {
return ctx;
};

/**
* SYM visitor. Looks up symbol (word name) and if `state.word` is true,
* pushes word on (temp) stack (created by `visitWord`), else executes
* word. Throws error if unknown word.
*
* @param node
* @param ctx
* @param state
*/
const visitSym = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) => {
const w = resolveSym(node, ctx);
if (state.word) {
Expand All @@ -119,15 +154,33 @@ const visitSym = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) => {
}
};

/**
* VAR_DEREF visitor. If `state.word` is true, pushes `loadkey(id)` on
* (temp) stack (created by `visitWord`), else attempts to resolve var
* and pushes its value on stack. Throws error if unknown var.
*
* @param node
* @param ctx
* @param state
*/
const visitDeref = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) => {
if (state.word && node.type === NodeType.VAR_DEREF) {
if (state.word) {
ctx[0].push(pf.loadkey(node.id));
} else {
ctx[0].push(resolveVar(node, ctx));
}
return ctx;
};

/**
* VAR_STORE visitor. If `state.word` is true, pushes `storekey(id)` on
* (temp) stack (created by `visitWord`), else pushes var name on stack
* and calls `store` to save value in env.
*
* @param node
* @param ctx
* @param state
*/
const visitStore = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) => {
const id = node.id;
if (state.word) {
Expand All @@ -140,6 +193,11 @@ const visitStore = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) =>
};

/**
* WORD visitor to create new word definition. Sets `state.word` to
* true, builds temp stack context and calls `visit()` for all child
* nodes. Then calls `word()` to compile function and stores it in
* `env.__words` object.
*
* @param node
* @param ctx
* @param state
Expand All @@ -160,6 +218,15 @@ const visitWord = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) =>
return ctx;
}

/**
* ARRAY visitor for arrays/quotations. If `state.word` is true, pushes
* call to `resolveArray` on temp word stack, else calls `resolveArray`
* and pushes result on stack.
*
* @param node
* @param ctx
* @param state
*/
const visitArray = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) => {
if (state.word) {
ctx[0].push((_ctx) => (_ctx[0].push(resolveArray(node, _ctx)), _ctx));
Expand All @@ -169,11 +236,20 @@ const visitArray = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) =>
return ctx;
};

const visitMap = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) => {
/**
* OBJ visitor for object literals. If `state.word` is true, pushes call
* to `resolveObject` on temp word stack, else calls `resolveObject` and
* pushes result on stack.
*
* @param node
* @param ctx
* @param state
*/
const visitObject = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) => {
if (state.word) {
ctx[0].push((_ctx) => (_ctx[0].push(resolveMap(node, _ctx)), _ctx));
ctx[0].push((_ctx) => (_ctx[0].push(resolveObject(node, _ctx)), _ctx));
} else {
ctx[0].push(resolveMap(node, ctx));
ctx[0].push(resolveObject(node, ctx));
}
return ctx;
};
Expand Down

0 comments on commit 1c899a1

Please sign in to comment.