Skip to content

Commit

Permalink
WIP noImplicitAny
Browse files Browse the repository at this point in the history
  • Loading branch information
joews committed Mar 12, 2017
1 parent dd5cd18 commit 0bd315a
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 36 deletions.
12 changes: 12 additions & 0 deletions src/node-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
52 changes: 18 additions & 34 deletions src/unify.ts
Original file line number Diff line number Diff line change
@@ -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
}
Expand All @@ -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)
}

Expand All @@ -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)
}
Expand All @@ -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]])
}

11 changes: 9 additions & 2 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// _.extend, but immutable by default
export function extend (source, ...extensions) {
export function extend (source: any, ...extensions: any[]) {
return Object.assign({}, source, ...extensions)
}

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)
}

Expand All @@ -20,3 +20,10 @@ export function restAndLast<T> (arr: T[]): [T[], T] {
export function last<T> (arr: T[]): T {
return arr[arr.length - 1]
}

export function zip<A, B> (a: A[], b: B[]): [A, B][] {
return a.map((aValue, i): [A, B] => {
const bValue = b[i]
return [aValue, bValue]
})
}

0 comments on commit 0bd315a

Please sign in to comment.