def assign(self, index: int) -> Tuple[List[Node], 'Vector']: """Generate YOLOL assignment statements.""" assignments = [] nums = [] expressions = [n.evaluate() for n in self.nums] for i, expr in enumerate(expressions): ident = '{}{}_e{}'.format(Vector.PREFIX, index, i) var = Node(kind='variable', value=ident) asn = Node(kind='assignment', children=[var, expr]) assignments.append(asn) nums.append(Number(ident)) return assignments, Vector(nums)
def assign(self, index: int) -> Tuple[List[Node], 'Matrix']: """Generate YOLOL assignment statements.""" assignments = [] vecs = [] for i, v in enumerate(self.vecs): nums = [] for j, n in enumerate(v.nums): expr = n.evaluate() ident = '{}{}_r{}c{}'.format(Matrix.PREFIX, index, i, j) var = Node(kind='variable', value=ident) asn = Node(kind='assignment', children=[var, expr]) assignments.append(asn) nums.append(Number(ident)) vecs.append(Vector(nums)) return assignments, Matrix(vecs)
def matmul(self, other: 'Matrix') -> 'Matrix': """Multiply two matrices.""" if self._cols != other._rows: raise YovecError('cannot mulitply matrices with mismatching sizes') vecs = [] for i in range(self._rows): nums = [] for j in range(other._cols): n = Number(0) for k in range(other._rows): n = n.binary( 'add', self.vecs[i].nums[k].binary('mul', other.vecs[k].nums[j])) nums.append(n) vecs.append(Vector(nums)) return Matrix(vecs)
def len(self) -> Number: """Return the length of the vector.""" return Number(self.length)
def dot(self, other: 'Vector') -> Number: """Calculate the dot product of two vectors.""" n = Number(0) for ln, rn in zip(self.nums, other.nums): n = n.binary('add', ln.binary('mul', rn)) return n
def cols(self) -> Number: """Return the number of columns in the matrix.""" return Number(self._cols)
def rows(self) -> Number: """Return the number of rows in the matrix.""" return Number(self._rows)
def nexpr(self, env: Env, nexpr: Node) -> Tuple[Env, Number]: """Transpile a number expression to YOLOL.""" logger.debug('transpiling number expression - {}'.format(nexpr)) if not is_nexpr(nexpr.kind): raise YovecError('expected number expression, but got {}'.format( nexpr.kind)) elif nexpr.kind == 'num_binary': env, lnum = self.nexpr(env, nexpr.children[0]) ops = nexpr.children[1::2] rnums = nexpr.children[2::2] for op, rnum in zip(ops, rnums): env, rnum = self.nexpr(env, rnum) lnum = lnum.binary(op.kind, rnum) return env, lnum elif nexpr.kind == 'num_unary': env, num = self.nexpr(env, nexpr.children[-1]) for op in reversed(nexpr.children[:-1]): num = num.unary(op.kind) return env, num elif nexpr.kind == 'reduce': op = nexpr.children[0] env, vec = self.vexpr(env, nexpr.children[1]) return env, vec.reduce(op.kind) elif nexpr.kind == 'dot': env, lvec = self.vexpr(env, nexpr.children[0]) env, rvec = self.vexpr(env, nexpr.children[1]) return env, lvec.dot(rvec) elif nexpr.kind == 'len': env, vec = self.vexpr(env, nexpr.children[0]) return env, vec.len() elif nexpr.kind == 'rows': env, mat = self.mexpr(env, nexpr.children[0]) return env, mat.rows() elif nexpr.kind == 'cols': env, mat = self.mexpr(env, nexpr.children[0]) return env, mat.cols() elif nexpr.kind == 'vec_elem': env, vec = self.vexpr(env, nexpr.children[0]) index = nexpr.children[1].value try: return env, vec.elem(int(index)) except ValueError: raise YovecError('invalid element index: {}'.format(index)) elif nexpr.kind == 'mat_elem': env, mat = self.mexpr(env, nexpr.children[0]) row = nexpr.children[1].value col = nexpr.children[2].value try: return env, mat.elem(int(row), int(col)) except ValueError: raise YovecError('invalid element indices: {}, {}'.format( row, col)) elif nexpr.kind == 'external': ident = nexpr.value _ = env.target(ident) return env, Number(ident) elif nexpr.kind == 'variable': ident = nexpr.value value, _ = env.var(ident) if type(value) != Number: raise YovecError( 'expected variable {} to be number, but got {}'.format( ident, value.class_name)) return env, value elif nexpr.kind == 'call': ident = nexpr.children[0].value macro = env.macro(ident) if macro.return_type != 'number': raise YovecError( 'expected macro to return number expression, but got {} expression' .format(macro.return_type)) args = nexpr.children[1].children return self.nexpr(env, macro.call(args)) elif nexpr.kind == 'number': try: return env, Number(int(nexpr.value)) except ValueError: return env, Number(float(nexpr.value)) else: raise AssertionError('nexpr fallthough: {}'.format(nexpr))