From 0bd315a0101b0fe43f1cf80931d962d101b18f1d Mon Sep 17 00:00:00 2001 From: Joe Whitfield-Seed Date: Sun, 12 Mar 2017 23:37:21 +0000 Subject: [PATCH] WIP noImplicitAny --- src/node-types.ts | 12 +++++++++++ src/unify.ts | 52 ++++++++++++++++------------------------------- src/util.ts | 11 ++++++++-- 3 files changed, 39 insertions(+), 36 deletions(-) diff --git a/src/node-types.ts b/src/node-types.ts index 7a0929a..9b1dcd3 100644 --- a/src/node-types.ts +++ b/src/node-types.ts @@ -156,6 +156,18 @@ export interface TypedIfNode extends AstIfNode, Typed { elseBranch: TypedNode } +// +// Nodes with shared traits +// +export type TypedLiteralNode = TypedStringNode | TypedBooleanNode | TypedNumeralNode + +// +// Guard functions +// +export function isTypedLiteralNode (node: TypedNode): node is TypedLiteralNode { + return ['Bool', 'Str', 'Numeral'].includes(node.type) +} + // // Runtime values // TODO diff --git a/src/unify.ts b/src/unify.ts index 97ea0d6..3bc2ed7 100644 --- a/src/unify.ts +++ b/src/unify.ts @@ -1,13 +1,17 @@ import PeachError from './errors' import { isArray, isEqual } from './array' +import { zip } from './util' +import { TypedNode, TypedLiteralNode, TypedDestructuredArrayNode, Value, isTypedLiteralNode } from './node-types' + +// FIXME tagged union - with didMatch: false, there are never bindings. +type binding = { [name: string]: Value } -// FIXME union type - with didMatch: false, there are never bindings. interface unification { didMatch: boolean, - bindings: object + bindings: binding } -export default function unify (patterns, values) : unification { +export default function unify (patterns: TypedNode[], values: Value[]): unification { if (patterns.length !== values.length) { return didNotMatch } @@ -25,24 +29,23 @@ export default function unify (patterns, values) : unification { return didMatch(bindings) } -function unifyOne (pattern, value) { - // TODO value equality operator - if (isValue(pattern) && pattern.value === value) { +function unifyOne (pattern: TypedNode, value: Value): binding { + if (isTypedLiteralNode(pattern) && pattern.value === value) { // the pattern matched, but there is nothing to bind return {} } - if (isName(pattern)) { + if (pattern.type === 'Name') { // the pattern matched; return a new binding return { [pattern.name]: value } } // TODO generic value equality - if (isArray(pattern) && isEqual(pattern.values, value)) { + if (pattern.type === 'Array' && isEqual(pattern.values, value)) { return {} } - if (isDestructuredArray(pattern)) { + if (pattern.type === 'DestructuredArray') { return destructure(pattern, value) } @@ -51,14 +54,14 @@ function unifyOne (pattern, value) { } // TODO this will need to change when Array is a wrapped type -function destructure ({ head, tail }, array) { - if (array.length === 0) { +function destructure ({ head, tail }: TypedDestructuredArrayNode, values: Value[]): binding { + if (values.length === 0) { throw new PeachError(`Empty arrays cannot be destructured because they don't have a head`) } - const boundHead = unifyOne(head, array[0]) + const boundHead = unifyOne(head, values[0]) if (boundHead !== null) { - const boundTail = unifyOne(tail, array.slice(1)) + const boundTail = unifyOne(tail, values.slice(1)) if (boundTail) { return Object.assign(boundHead, boundTail) } @@ -67,33 +70,14 @@ function destructure ({ head, tail }, array) { return null } -const didNotMatch : unification = { +const didNotMatch: unification = { didMatch: false, bindings: {} } -function didMatch (bindings) : unification { +function didMatch (bindings: binding) : unification { return { didMatch: true, bindings } } - -// TODO these belong with type definitions -function isName ({ type }) { - return type === 'Name' -} - -function isValue ({ type }) { - return ['Bool', 'Str', 'Numeral'].includes(type) -} - -function isDestructuredArray ({ type }) { - return type === 'DestructuredArray' -} - -// TODO stdlib -function zip (arrayA, arrayB) { - return arrayA.map((e, i) => [e, arrayB[i]]) -} - diff --git a/src/util.ts b/src/util.ts index 3443ea2..bbf2b62 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,5 +1,5 @@ // _.extend, but immutable by default -export function extend (source, ...extensions) { +export function extend (source: any, ...extensions: any[]) { return Object.assign({}, source, ...extensions) } @@ -7,7 +7,7 @@ export const clone = extend // shortcut for creating an object with the given prototype and // properties with default behaviour -export function create (proto, properties = null) { +export function create (proto: any, properties: any = null) { return Object.assign(Object.create(proto), properties) } @@ -20,3 +20,10 @@ export function restAndLast (arr: T[]): [T[], T] { export function last (arr: T[]): T { return arr[arr.length - 1] } + +export function zip (a: A[], b: B[]): [A, B][] { + return a.map((aValue, i): [A, B] => { + const bValue = b[i] + return [aValue, bValue] + }) +}