func eval(s []byte, header Header, tuple Tuple, line opLine) ([]byte, error) { switch line.op { case Pusha: attr, pos, err := header.AttrByName(line.arg) if err != nil { return nil, fmt.Errorf("lql: error executing : %v", err) } s = append(s, tuple[pos:pos+attr.Typ.Len()]...) break case Pushv: s = append(s, line.value...) break case OpAdd: typ, ok := typer.Get(line.arg) if !ok { fmt.Errorf("lql: unknown type") } adder, ok := typ.(typer.Adder) if !ok { fmt.Errorf("lql: type %v is not an Adder", typ.Len()) } buf1 := s[len(s)-typ.Len()*2 : len(s)-typ.Len()] buf2 := s[len(s)-typ.Len():] adder.Add(buf1, buf1, buf2) s = s[:len(s)-typ.Len()] break case OpMult: typ, ok := typer.Get(line.arg) if !ok { fmt.Errorf("lql: unknown type") } multer, ok := typ.(typer.Multer) if !ok { fmt.Errorf("lql: type %v is not a Multer", typ.Len()) } buf1 := s[len(s)-typ.Len()*2 : len(s)-typ.Len()] buf2 := s[len(s)-typ.Len():] multer.Mult(buf1, buf1, buf2) s = s[:len(s)-typ.Len()] break case OpGT: typ, ok := typer.Get(line.arg) if !ok { return nil, fmt.Errorf("lql: unknown type") } var vb1, vb2 []byte vb1, s = s[len(s)-typ.Len():], s[:len(s)-typ.Len()] vb2, s = s[len(s)-typ.Len():], s[:len(s)-typ.Len()] if bytes.Compare(vb1, vb2) > 0 { s = append(s, byte(0)) } else { s = append(s, byte(1)) } break case OpOr: v1 := s[len(s)-1] v2 := s[len(s)-2] if v1 > 0 || v2 > 0 { s[len(s)-2] = 1 } else { s[len(s)-2] = 0 } s = s[:len(s)-1] break case OpEq: typ, ok := typer.Get(line.arg) if !ok { return nil, fmt.Errorf("lql: unknown type") } var vb1, vb2 []byte vb1, s = s[len(s)-typ.Len():], s[:len(s)-typ.Len()] vb2, s = s[len(s)-typ.Len():], s[:len(s)-typ.Len()] if bytes.Compare(vb1, vb2) == 0 { s = append(s, byte(1)) } else { s = append(s, byte(0)) } break default: panic("not a operator") break } return s, nil }
func (m *Machine) Execute(line string) (info string, err error) { op, args, err := extract(line) if err != nil { return "", fmt.Errorf("lql: error executing %v: %v", line, err) } switch op { case Load: if len(args) != 2 { return "", fmt.Errorf("lql: 2 argument needed for Load, %d provided", len(args)) } file, err := os.Open(args[1]) if err != nil { return "", fmt.Errorf("lql: Error when opening file: '%s'", err) } reader := csv.NewReader(file) records, err := reader.ReadAll() if err != nil { return "", fmt.Errorf("lql: Error reading file: %s", err) } header, records := records[0], records[1:] attrs := make(Header, 0, len(header)) for _, v := range header { nameType := strings.Split(v, ":") if len(nameType) != 2 { return "", fmt.Errorf("lql: column header %s must have a name and a type %s", v) } typ, ok := typer.Get(nameType[1]) if !ok { return "", fmt.Errorf("lql: type %s not registered", nameType[1]) } attrs = append(attrs, Attr{nameType[0], typ}) } table := NewRelation(attrs) for _, v := range records { tuple, err := table.NewTuple(v) if err != nil { return "", fmt.Errorf("lql: unable to add tuple, reason: %s", err) } table.Add(tuple) } m.rels[args[0]] = *table break case Print: if len(args) != 1 { return "", fmt.Errorf("lql: 1 argument needed for Print, %d provided", len(args)) } table, ok := m.rels[args[0]] if !ok { return "", fmt.Errorf("lql: unknown table, %s ", args[0]) } //fmt.Println(table) info = fmt.Sprint(table) case Join: if len(args) != 3 { return "", fmt.Errorf("lql: Join must have 3 arguments") } table1, ok1 := m.rels[args[1]] if !ok1 { return "", fmt.Errorf("lql: table %s unknow", args[1]) } table2, ok2 := m.rels[args[2]] if !ok2 { return "", fmt.Errorf("lql: table %s unknow", args[2]) } newTable := join(table1, table2) m.rels[args[0]] = *newTable break case Rename: if len(args) != 4 { return "", fmt.Errorf("lql: Rename must have 4 arguments") } tableSrc, ok1 := m.rels[args[1]] if !ok1 { return "", fmt.Errorf("lql: table %s unknow", args[1]) } newTable := rename(tableSrc, args[2], args[3]) m.rels[args[0]] = *newTable break case Project: if len(args) < 3 { return "", fmt.Errorf("lql: Project must have at least 3 arguments") } tableSrc, ok1 := m.rels[args[1]] if !ok1 { return "", fmt.Errorf("lql: table %s unknow", args[1]) } newTable := project(tableSrc, args[2:]) m.rels[args[0]] = *newTable case Restrict: if len(args) != 2 { return "", fmt.Errorf("lql: Restrict must have 2 arguments") } tableSrc, ok1 := m.rels[args[1]] if !ok1 { return "", fmt.Errorf("lql: table %s unknow", args[1]) } newTable := m.restrict(tableSrc, m.pred) m.pred = m.pred[0:0] m.rels[args[0]] = *newTable break case OpEq: if len(args) != 1 { return "", fmt.Errorf("lql: Op must have 1 arguments") } l := opLine{op: OpEq, arg: args[0], value: nil} m.pred = append(m.pred, l) break case OpGT: if len(args) != 1 { return "", fmt.Errorf("lql: Op must have 1 arguments") } l := opLine{op: OpGT, arg: args[0], value: nil} m.pred = append(m.pred, l) break case OpAnd: if len(args) != 0 { return "", fmt.Errorf("lql: Op must have 0 arguments") } l := opLine{op: OpAnd, arg: "", value: nil} m.pred = append(m.pred, l) break case OpOr: if len(args) != 0 { return "", fmt.Errorf("lql: Op must have 0 arguments") } l := opLine{op: OpOr, arg: "", value: nil} m.pred = append(m.pred, l) break case OpAdd: if len(args) != 1 { return "", fmt.Errorf("lql: Op must have 1 arguments") } l := opLine{op: OpAdd, arg: args[0], value: nil} m.pred = append(m.pred, l) break case OpMult: if len(args) != 1 { return "", fmt.Errorf("lql: Op must have 1 arguments") } l := opLine{op: OpMult, arg: args[0], value: nil} m.pred = append(m.pred, l) break case Pusha: if len(args) != 1 { return "", fmt.Errorf("lql: Pushr must have 1 arguments") } l := opLine{op: Pusha, arg: args[0], value: nil} m.pred = append(m.pred, l) break case Pushv: if len(args) != 2 { return "", fmt.Errorf("lql: Pushv must have 2 arguments") } lTyp, ok := typer.Get(args[0]) if !ok { return "", fmt.Errorf("lql: Typ %v unknown", args[0]) } if t, ok := lTyp.(typer.Unquoter); ok { unquoted, err := t.Unquote(args[1]) args[1] = unquoted if err != nil { return "", fmt.Errorf("lql: Could not unqote %v", args[1]) } } v := make([]byte, lTyp.Len()) err := lTyp.FromString(v, args[1]) if err != nil { return "", fmt.Errorf("lql: Error parsing value %v of type %v", args[1], args[0]) } l := opLine{op: Pushv, arg: args[0], value: v} m.pred = append(m.pred, l) break default: return "", fmt.Errorf("lql: Op code '%s' not implemented", op) break } return }