UNPKG

khufu

Version:

A template language for incremental-dom or DSL for javascript views

148 lines (142 loc) 5.11 kB
import * as T from "babel-types" import {parse_tree_error} from './compiler' import {get_var} from './vars' const GLOBAL_NAMES = new Set([ 'true', 'false', 'null', ]) export function compile(item, path, opt) { switch(item[0]) { case 'string': { let [_string, value] = item; return T.stringLiteral(value); } case 'template': { let [_template, items] = item; let quasis = [] let exprs = [] for(var [kind, val] of items) { if(kind == 'const') { quasis.push(T.templateElement({raw: val})) } else { exprs.push(compile(val, path, opt)) } } quasis[quasis.length-1].tail = true; return T.templateLiteral(quasis, exprs); } case 'apply_template': { let [_apply_template, expr, items] = item; let tag = compile(expr, path, opt) let quasis = [] let exprs = [] for(var [kind, val] of items) { if(kind == 'const') { quasis.push(T.templateElement({raw: val})) } else { exprs.push(compile(val, path, opt)) } } quasis[quasis.length-1].tail = true; return T.taggedTemplateExpression(tag, T.templateLiteral(quasis, exprs)); } case 'number': { let [_number, value] = item; return T.numericLiteral(Number(value)); } case 'list': { let [_list, expressions] = item; return T.arrayExpression(expressions.map(x => compile(x, path, opt))) } case 'object': { let [_object, expressions] = item; return T.objectExpression( expressions.map(([k, v]) => { if(/[a-zA-Z_][a-zA_Z_0-9]*/.exec(k)) { return T.objectProperty(T.identifier(k), compile(v, path, opt), false, true, null); } else { return T.objectProperty(T.stringLiteral(k), compile(v, path, opt), true, false, null) } })) } case 'name': { let [_name, name] = item; if(GLOBAL_NAMES.has(name)) { return T.identifier(name); } return get_var(path, name, item); } case 'store': { let [_store, name] = item let store = get_var(path, name, item); let state = path.scope.getData('khufu:store:state:' +name); if(!state) { state = path.scope.generateUidIdentifier(name + '_state'); path.scope.push({ id: state, init: T.callExpression(T.memberExpression( store, T.identifier('getState')), []), kind: 'let', }) path.scope.setData('khufu:store:state:' + name, state); } return state; } case 'raw_store': { let [_raw_store, name] = item return get_var(path, name, item); } case 'attr': { let [_attr, object, name] = item return T.memberExpression(compile(object, path, opt), T.identifier(name)) } case 'index': { let [_index, object, key] = item return T.memberExpression(compile(object, path, opt), compile(key, path, opt), true) } case 'call': { let [_call, fun, args] = item return T.callExpression(compile(fun, path, opt), args.map(x => compile(x, path, opt))) } case 'unary': { let [_unary, op, value] = item return T.unaryExpression(op, compile(value, path, opt)) } case 'binop': { let [_binop, oper, left, right] = item return T.binaryExpression(oper, compile(left, path, opt), compile(right, path, opt)) } case 'logop': { let [_logop, oper, left, right] = item return T.logicalExpression(oper, compile(left, path, opt), compile(right, path, opt)) } case 'ternary': { let [_ternary, cond, positive, negative] = item return T.conditionalExpression( compile(cond, path, opt), compile(positive, path, opt), compile(negative, path, opt)) } case 'if': { let [_if, cond, norm, alter] = item return T.conditionalExpression( compile(cond, path, opt), compile(norm, path, opt), compile(alter, path, opt)) } default: throw parse_tree_error('Unknown expression', item) } }