func prep(expr *ast.Expr, expType types.Type) (uniq string, err error) { if expr.Function != nil { fnc := expr.GetFunction() uniq, err = WhichFunc(fnc) if err != nil { return "", err } typ, err := funcs.Out(uniq) if err != nil { return "", err } if typ != expType { return "", &errExpected{expType.String(), expr.String()} } return uniq, err } if expr.List != nil { if !types.IsList(expType) { return "", &errExpected{expType.String(), expr.String()} } } typ, err := Which(expr) if err != nil { return "", err } if typ != expType { return "", &errExpected{expType.String(), expr.String()} } return "", nil }
func composeInts(expr *ast.Expr) (funcs.Ints, error) { uniq, err := prep(expr, types.LIST_INT) if err != nil { return nil, err } if expr.List != nil { vs, err := newValues(expr.GetList().GetElems()) if err != nil { return nil, err } bs := make([]funcs.Int, len(vs)) var ok bool for i := range vs { bs[i], ok = vs[i].(funcs.Int) if !ok { return nil, &errExpected{types.SINGLE_INT.String(), expr.String()} } } return funcs.NewListOfInt(bs), nil } values, err := newValues(expr.GetFunction().GetParams()) if err != nil { return nil, err } return funcs.NewIntsFunc(uniq, values...) }
//ConvertBuiltInIntoFunction converts a BuiltIn Expr into a Function Expr. func ConvertBuiltInIntoFunction(e *ast.Expr) (*ast.Expr, error) { if e.BuiltIn == nil { return e, nil } s := e.GetBuiltIn().GetSymbol().GetValue() right := e.GetBuiltIn().GetExpr().Clone() typ, err := Which(right) if err != nil { return nil, err } if types.IsList(typ) { typ = types.ListToSingle(typ) } left := ast.NewVar(typ) funcName := ast.BuiltInFunctionName(s) e2 := ast.NewNestedFunction(funcName, left, right) if funcName == "regex" { e2 = ast.NewNestedFunction(funcName, right, ast.NewVar(types.SINGLE_STRING)) } else if funcName == "type" { e2 = ast.NewNestedFunction(funcName, right) } return e2, nil }
func newValue(p *ast.Expr) (interface{}, error) { if p.Terminal != nil && p.GetTerminal().Variable != nil { return composeVariable(p.GetTerminal().Variable), nil } typ, err := Which(p) if err != nil { return nil, err } switch typ { case types.SINGLE_DOUBLE: return composeDouble(p) case types.SINGLE_INT: return composeInt(p) case types.SINGLE_UINT: return composeUint(p) case types.SINGLE_BOOL: return composeBool(p) case types.SINGLE_STRING: return composeString(p) case types.SINGLE_BYTES: return composeBytes(p) case types.LIST_DOUBLE: return composeDoubles(p) case types.LIST_INT: return composeInts(p) case types.LIST_UINT: return composeUints(p) case types.LIST_BOOL: return composeBools(p) case types.LIST_STRING: return composeStrings(p) case types.LIST_BYTES: return composeListOfBytes(p) } panic("not implemented") }
func composeInt(expr *ast.Expr) (funcs.Int, error) { uniq, err := prep(expr, types.SINGLE_INT) if err != nil { return nil, err } if expr.Terminal != nil { if expr.GetTerminal().Variable != nil { return funcs.IntVar(), nil } else { return funcs.IntConst(expr.GetTerminal().GetIntValue()), nil } } values, err := newValues(expr.GetFunction().GetParams()) if err != nil { return nil, err } return funcs.NewIntFunc(uniq, values...) }
func composeString(expr *ast.Expr) (funcs.String, error) { uniq, err := prep(expr, types.SINGLE_STRING) if err != nil { return nil, err } if expr.Terminal != nil { if expr.GetTerminal().Variable != nil { return funcs.StringVar(), nil } else { return funcs.StringConst(expr.GetTerminal().GetStringValue()), nil } } values, err := newValues(expr.GetFunction().GetParams()) if err != nil { return nil, err } return funcs.NewStringFunc(uniq, values...) }
func composeBool(expr *ast.Expr) (funcs.Bool, error) { uniq, err := prep(expr, types.SINGLE_BOOL) if err != nil { return nil, err } if expr.Terminal != nil { if expr.GetTerminal().Variable != nil { return funcs.BoolVar(), nil } else { return funcs.BoolConst(expr.GetTerminal().GetBoolValue()), nil } } values, err := newValues(expr.GetFunction().GetParams()) if err != nil { return nil, err } return funcs.NewBoolFunc(uniq, values...) }
func composeDouble(expr *ast.Expr) (funcs.Double, error) { uniq, err := prep(expr, types.SINGLE_DOUBLE) if err != nil { return nil, err } if expr.Terminal != nil { if expr.GetTerminal().Variable != nil { return funcs.DoubleVar(), nil } else { return funcs.DoubleConst(expr.GetTerminal().GetDoubleValue()), nil } } values, err := newValues(expr.GetFunction().GetParams()) if err != nil { return nil, err } return funcs.NewDoubleFunc(uniq, values...) }
//Which returns the type that the expression will return. func Which(expr *ast.Expr) (types.Type, error) { if expr.Terminal != nil { term := expr.GetTerminal() if term.DoubleValue != nil { return types.SINGLE_DOUBLE, nil } if term.IntValue != nil { return types.SINGLE_INT, nil } if term.UintValue != nil { return types.SINGLE_UINT, nil } if term.BoolValue != nil { return types.SINGLE_BOOL, nil } if term.StringValue != nil { return types.SINGLE_STRING, nil } if term.BytesValue != nil { return types.SINGLE_BYTES, nil } if term.Variable != nil { return term.Variable.Type, nil } } if expr.List != nil { return expr.GetList().GetType(), nil } if expr.Function != nil { fnc := expr.GetFunction() uniq, err := WhichFunc(fnc) if err != nil { return 0, err } return funcs.Out(uniq) } return 0, &errUnknownType{expr} }
func exprToName(e *ast.Expr) *ast.NameExpr { if e.GetBuiltIn() != nil { if e.GetBuiltIn().GetSymbol().String() == "==" { if e.GetBuiltIn().GetExpr().GetTerminal() != nil { t := e.GetBuiltIn().GetExpr().GetTerminal() if t.DoubleValue != nil { return ast.NewDoubleName(t.GetDoubleValue()) } if t.IntValue != nil { return ast.NewIntName(t.GetIntValue()) } if t.UintValue != nil { return ast.NewUintName(t.GetUintValue()) } if t.BoolValue != nil { return ast.NewBoolName(t.GetBoolValue()) } if t.StringValue != nil { return ast.NewStringName(t.GetStringValue()) } if t.BytesValue != nil { return ast.NewBytesName(t.GetBytesValue()) } } else { panic("todo") } } else { panic("todo") } } if e.GetFunction() != nil { if e.GetFunction().GetName() == "not" { return ast.NewAnyNameExcept(exprToName(e.GetFunction().GetParams()[0])) } if e.GetFunction().GetName() == "or" { return ast.NewNameChoice( exprToName(e.GetFunction().GetParams()[0]), exprToName(e.GetFunction().GetParams()[1]), ) } panic("todo") } if e.GetTerminal() != nil { if e.GetTerminal().BoolValue != nil { if e.GetTerminal().GetBoolValue() { return ast.NewAnyName() } else { panic("todo") } } else { panic("todo") } } panic("todo") }