import * as AST from "../../ast" ; import { nodeFromExpression } from "../create" ; import { StreamPort } from "../ports/stream" ; import { Scope } from "../scopes/scope" ; import * as Types from "../types" ; import * as Values from "../values" ; import { Node } from "./node" ; export class BinaryExpression extends Node { private nodes : Node [ ] ; private operator : string ; constructor ( definition , scope ) { super ( "Binary" , definition ) ; this . operator = definition . operator ; this . nodes = [ ] ; this . nodes . push ( nodeFromExpression ( definition . left , scope ) ) ; this . nodes . push ( nodeFromExpression ( definition . right , scope ) ) ; this . addInPorts ( this . nodes ) ; this . outPorts . push ( new StreamPort ( ( type , offset ) => this . fetchData ( type , offset ) ) ) ; } private fetchData ( dataType , offset ) { let type = dataType ; if ( [ "+" , "-" , "*" , "/" , "%" ] . indexOf ( this . operator ) === - 1 ) { type = new Types . Some ( ) ; } const left = this . inPorts [ 0 ] . getData ( type , offset ) ; const right = this . inPorts [ 1 ] . getData ( type , offset ) ; if ( ! Types . checkType ( left . type , right . type ) ) { return new Values . ErrorValue ( "Types should be equal for binary operation " + JSON . stringify ( left . type ) + " " + JSON . stringify ( right . type ) ) ; } return this . processPair ( left , right ) ; } private processPair ( left , right ) { if ( left . type instanceof Types . Integer ) { return this . processIntPair ( left as Values . Integer , right as Values . Integer ) ; } if ( left . type instanceof Types . Float ) { return this . processFloatPair ( left as Values . Float , right as Values . Float ) ; } if ( left . type instanceof Types . Boolean ) { return this . processBooelanPair ( left as Values . Boolean , right as Values . Boolean ) ; } if ( left instanceof Values . StreamEnd ) { return left ; } if ( ( left instanceof Values . StreamElement ) && ( right instanceof Values . StreamElement ) ) { return new Values . StreamElement ( this . processPair ( left . value , right . value ) ) ; } return new Values . ErrorValue ( "Unsupported types " + left . type . name ) ; } private processBooelanPair ( left , right ) { if ( this . operator === "|" ) { return new Values . Boolean ( left . value || right . value ) ; } if ( this . operator === "&" ) { return new Values . Boolean ( left . value && right . value ) ; } return new Values . ErrorValue ( "Unknown operation " + this . operator ) ; } private processIntPair ( left , right ) { if ( this . operator === "+" ) { return new Values . Integer ( left . value + right . value ) ; } if ( this . operator === "-" ) { return new Values . Integer ( left . value - right . value ) ; } if ( this . operator === "*" ) { return new Values . Integer ( left . value * right . value ) ; } if ( this . operator === "/" ) { return new Values . Integer ( Math . trunc ( left . value / right . value ) ) ; } if ( this . operator === "%" ) { return new Values . Integer ( left . value % right . value ) ; } if ( this . operator === "<" ) { return new Values . Boolean ( left . value < right . value ) ; } if ( this . operator === ">" ) { return new Values . Boolean ( left . value > right . value ) ; } if ( this . operator === "<=" ) { return new Values . Boolean ( left . value <= right . value ) ; } if ( this . operator === ">=" ) { return new Values . Boolean ( left . value >= right . value ) ; } if ( this . operator === "=" ) { return new Values . Boolean ( left . value === right . value ) ; } if ( this . operator === "/=" ) { return new Values . Boolean ( left . value !== right . value ) ; } return new Values . ErrorValue ( "Unknown operation " + this . operator ) ; } private processFloatPair ( left , right ) { if ( this . operator === "+" ) { return new Values . Float ( left . value + right . value ) ; } if ( this . operator === "-" ) { return new Values . Float ( left . value - right . value ) ; } if ( this . operator === "*" ) { return new Values . Float ( left . value * right . value ) ; } if ( this . operator === "/" ) { return new Values . Float ( left . value / right . value ) ; } if ( this . operator === "<" ) { return new Values . Boolean ( left . value < right . value ) ; } if ( this . operator === ">" ) { return new Values . Boolean ( left . value > right . value ) ; } if ( this . operator === "<=" ) { return new Values . Boolean ( left . value <= right . value ) ; } if ( this . operator === ">=" ) { return new Values . Boolean ( left . value >= right . value ) ; } if ( this . operator === "=" ) { return new Values . Boolean ( left . value === right . value ) ; } if ( this . operator === "/=" ) { return new Values . Boolean ( left . value !== right . value ) ; } return new Values . ErrorValue ( "Unknown operation " + this . operator ) ; } }