UNPKG

costreamjs

Version:

A high-performance streaming programming language for parallel architecture. This repo (js-version) is created for better using & reading & debugging.

135 lines (126 loc) 4.74 kB
import { expNode, unaryNode, binopNode, ternaryNode, parenNode, callNode, constantNode, castNode } from "./node.js" import { error } from "../utils" import { top } from "../FrontEnd/global" import { matrix_section } from "./node.js" import { matrix_constant } from "./node.js" import { checkShape } from "../FrontEnd/checkShape" /** * 加载常量传播插件后,表达式 node 可以计算数值 */ expNode.prototype.getValue = function () { //异步计算 value 值, 为了常量传播保留这个接口 Object.defineProperty(this, 'value', { enumerable: false, get: function () { return this.getValue() }, set: function () { error("请不要手动给 value 赋值.", this) } }) } ternaryNode.prototype.getValue = function () { return this.first.value ? this.second.value : this.third.value } parenNode.prototype.getValue = function () { return this.exp.value } /** * 目前只是简单计算值,后续常量传播时要修改此函数 */ unaryNode.prototype.getValue = function () { if (this.first == "+") return this.second.value if (this.first == "-") return -this.second.value if (this.first == "~") return ~this.second.value if (this.first == "!") return !this.second.value if(this.first == "++"){ // ++i 的情况 if(typeof this.second !== 'string') error(this._loc, `++ 运算符的操作对象必须是变量`) let oldVal = top.getVariableValue(this.second) top.setVariableValue(this.first, oldVal+1) return oldVal+1 }else if(this.second == "++"){ // i++ 的情况 if(typeof this.first !== 'string') error(this._loc, `++ 运算符的操作对象必须是变量`) let oldVal = top.getVariableValue(this.first) top.setVariableValue(this.first, oldVal+1) return oldVal } return NaN } castNode.prototype.getValue = function (){ return this.type == 'int' ? Math.floor(this.exp.value) : this.exp.value } Object.defineProperty(String.prototype,'value',{ get(){ if(!Number.isNaN(parseFloat(this))){ return parseFloat(this); // 如果这个字符串本身就是一个数字, 则直接返回, 例如'0; } return top.LookupIdentifySymbol(this).value; } }) Object.defineProperty(Number.prototype,'value',{ get(){ return this } }) binopNode.prototype.getValue = function () { var handlers = { '+': (a, b) => a.value + b.value, '-': (a, b) => a.value - b.value, '*': (a, b) => a.value * b.value, '/': (a, b) => a.value / b.value, '%': (a, b) => a.value % b.value, '|': (a, b) => a.value | b.value, '&': (a, b) => a.value & b.value, '^': (a, b) => a.value ^ b.value, '<': (a, b) => a.value < b.value, '>': (a, b) => a.value > b.value, '==': (a, b) => a.value == b.value, '!=': (a, b) => a.value != b.value, '<=': (a, b) => a.value <= b.value, '>=': (a, b) => a.value >= b.value, '>>': (a, b) => a.value >> b.value, '<<': (a, b) => a.value << b.value, //c++ 与 js 不同, c++的条件表达式返回 bool 值,而 js 是动态值 '||': (a, b) => !!(a.value || b.value), '&&': (a, b) => !!(a.value && b.value), '=' : (a, b) => top.setVariableValue(a, b.value), '+=': (a, b) => top.setVariableValue(a, a.value + b.value), '-=': (a, b) => top.setVariableValue(a, a.value - b.value), '*=': (a, b) => top.setVariableValue(a, a.value * b.value), '/=': (a, b) => top.setVariableValue(a, a.value / b.value), } if (this.op in handlers) { return this._value = handlers[this.op](this.left, this.right) } else { return NaN } } callNode.prototype.getValue = function () { if(typeof this.name === 'string'){ if(this.name === 'sin') return Math.sin(...this.arg_list) } else if(this.name instanceof binopNode){ if(this.name.op === '.' && ['rows','cols'].includes(this.name.right)){ const lshape = checkShape(this.name.left) return this.name.right === "rows" ? lshape[0] : lshape[1] } } return NaN } constantNode.prototype.getValue = function(){ return Number(this.source) } matrix_section.prototype.getValue = function(){ let values = top.LookupIdentifySymbol(this.exp).value debugger; if(this.slice_pair_list.length == 1){ let index = this.slice_pair_list[0].start return values[index].value }else{ throw new Error("FIXME 目前只处理了数组取地址, 未处理矩阵取址") } } matrix_constant.prototype.getValue = function(){ return this }