def compile_Parameter(expr: qlast.Base, *, ctx: context.ContextLevel) -> irast.Set: pt = ctx.arguments.get(expr.name) if pt is not None and not isinstance(pt, s_types.Type): pt = s_basetypes.normalize_type(pt, ctx.schema) return setgen.ensure_set(irast.Parameter(type=pt, name=expr.name), ctx=ctx)
def compile_Parameter(expr: qlast.Base, *, ctx: context.ContextLevel) -> irast.Set: if ctx.func is not None: raise errors.QueryError(f'"$parameters" cannot be used in functions', context=expr.context) pt = ctx.env.query_parameters.get(expr.name) return setgen.ensure_set(irast.Parameter(stype=pt, name=expr.name), ctx=ctx)
def compile_TypeCast(expr: qlast.Base, *, ctx: context.ContextLevel) -> irast.Base: target_typeref = typegen.ql_typeref_to_ir_typeref(expr.type, ctx=ctx) if (isinstance(expr.expr, qlast.Array) and not expr.expr.elements and target_typeref.maintype == 'array'): ir_expr = irast.Array() elif isinstance(expr.expr, qlast.Parameter): pt = typegen.ql_typeref_to_type(expr.type, ctx=ctx) param_name = expr.expr.name if param_name not in ctx.env.query_parameters: if ctx.env.query_parameters: first_key: str = next(iter(ctx.env.query_parameters)) if first_key.isdecimal(): if not param_name.isdecimal(): raise errors.QueryError( f'expected a positional argument', context=expr.expr.context) else: if param_name.isdecimal(): raise errors.QueryError(f'expected a named argument', context=expr.expr.context) ctx.env.query_parameters[param_name] = pt else: param_first_type = ctx.env.query_parameters[param_name] if not param_first_type.explicitly_castable_to(pt, ctx.env.schema): raise errors.QueryError( f'cannot cast ' f'{param_first_type.get_displayname(ctx.env.schema)} to ' f'{pt.get_displayname(ctx.env.schema)}', context=expr.expr.context) param = irast.Parameter(stype=pt, name=param_name, context=expr.expr.context) return setgen.ensure_set(param, ctx=ctx) else: with ctx.new() as subctx: # We use "exposed" mode in case this is a type of a cast # that wants view shapes, e.g. a std::json cast. We do # this wholesale to support tuple and array casts without # having to analyze the target type (which is cumbersome # in QL AST). subctx.expr_exposed = True ir_expr = dispatch.compile(expr.expr, ctx=subctx) new_stype = typegen.ql_typeref_to_type(expr.type, ctx=ctx) return cast.compile_cast(ir_expr, new_stype, ctx=ctx, srcctx=expr.expr.context)
def compile_func_to_ir(func, schema, *, anchors=None, security_context=None, modaliases=None, implicit_id_in_shapes=False): """Compile an EdgeQL function into EdgeDB IR.""" if debug.flags.edgeql_compile: debug.header('EdgeQL Function') debug.print(func.get_code(schema)) trees = ql_parser.parse_block(func.get_code(schema) + ';') if len(trees) != 1: raise errors.InvalidFunctionDefinitionError( 'functions can only contain one statement') tree = trees[0] if modaliases: ql_parser.append_module_aliases(tree, modaliases) if anchors is None: anchors = {} anchors['__defaults_mask__'] = irast.Parameter( name='__defaults_mask__', stype=schema.get('std::bytes')) func_params = func.get_params(schema) pg_params = s_func.PgParams.from_params(schema, func_params) for pi, p in enumerate(pg_params.params): p_shortname = p.get_shortname(schema) anchors[p_shortname] = irast.Parameter(name=p_shortname, stype=p.get_type(schema)) if p.get_default(schema) is None: continue tree.aliases.append( qlast.AliasedExpr( alias=p_shortname, expr=qlast. IfElse(condition=qlast.BinOp(left=qlast.FunctionCall( func=('std', 'bytes_get_bit'), args=[ qlast.FuncArg(arg=qlast.Path( steps=[qlast.ObjectRef( name='__defaults_mask__')])), qlast.FuncArg(arg=qlast.IntegerConstant(value=str(pi))) ]), right=qlast.IntegerConstant( value='0'), op='='), if_expr=qlast.Path( steps=[qlast.ObjectRef(name=p_shortname)]), else_expr=qlast._Optional( expr=p.get_ql_default(schema))))) ir = compile_ast_to_ir(tree, schema, anchors=anchors, func=func, security_context=security_context, modaliases=modaliases, implicit_id_in_shapes=implicit_id_in_shapes) return ir