import * as AST from "../../ast" ; import { nodeFromExpression } from "../create" ; import { Node } from "../nodes/node" ; import { Port } from "../ports/port" ; import * as Types from "../types" ; import { ReadyType } from "../types/ready" ; import * as Values from "../values" ; import { Scope } from "./scope" ; export class FlatScope implements Scope { public parentScope ? : Scope ; public oldScope ? : Scope ; public definitions : Map < string , Port [ ] > ; public constructor ( parent ) { this . parentScope = parent ; this . definitions = new Map ( ) ; } public resolve ( name , type , offset ) { if ( offset === - 1 && this . oldScope ) { return this . oldScope . resolve ( name , type , 0 ) ; } if ( this . definitions . has ( name ) ) { const candidates = this . definitions . get ( name ) ; for ( const port of candidates ! ) { const value = port . getData ( new Types . Some ( ) , offset ) ; if ( Types . checkType ( value . type , type ) ) { return value ; } } } if ( ! this . parentScope ) { return new Values . ErrorValue ( "Cannot resolve name " + name ) ; } return this . parentScope . resolve ( name , type , offset ) ; } public addFromAST ( definitions ) { for ( const d of definitions ) { if ( d . left . length !== d . right . length && d . right . length !== 1 ) { throw new Error ( "Definition arity doesn't match: " + String ( d . left . length ) + ":" + String ( d . right . length ) ) ; } const expressions = d . right . map ( ( e ) => nodeFromExpression ( e , this ) ) ; if ( expressions . length === 1 ) { expressions [ 0 ] . requestPorts ( d . left . length ) ; } for ( let i = 0 ; i < d . left . length ; i ++ ) { let currentDefinitions = [ ] ; if ( this . definitions . has ( d . left [ i ] ) ) { currentDefinitions = this . definitions . get ( d . left [ i ] ) ! ; } if ( expressions . length === 1 ) { currentDefinitions . push ( expressions [ 0 ] . outPorts [ i ] ) ; } else { currentDefinitions . push ( expressions [ i ] . outPorts [ 0 ] ) ; } this . definitions . set ( d . left [ i ] , currentDefinitions ) ; } } } public inject ( name , port ) { let currentDefinitions = [ ] ; if ( this . definitions . has ( name ) ) { currentDefinitions = this . definitions . get ( name ) ! ; } currentDefinitions . push ( port ) ; this . definitions . set ( name , currentDefinitions ) ; } } export function createFromMap ( parent , definitions ) { const scope = new FlatScope ( parent ) ; definitions . forEach ( ( nodes , key ) => { scope . definitions . set ( key , nodes . map ( ( n ) => n . outPorts [ 0 ] ) ) ; } ) ; return scope ; }