123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- package compiler
- import (
- "kumachan/lang/source"
- "kumachan/lang/typsys"
- "kumachan/lang/textual/ast"
- "kumachan/interpreter/program"
- )
- func checkCast(cast ast.Cast, in ast.Expr, cc *exprCheckContext) (*program.Expr, *source.Error) {
- var loc = cast.Location
- var target, err = cc.context.makeType(cast.Target)
- if err != nil { return nil, err }
- { var expr, err = cc.checkChildExpr(target.Type, in)
- if err != nil { return nil, err }
- return cc.assign(target, loc,
- program.Wrapper { Inner: expr })
- }
- }
- func checkPipeGet(get ast.PipeGet, in ast.Expr, cc *exprCheckContext) (*program.Expr, *source.Error) {
- var key = ast.Id2String(get.Key)
- var loc = get.Location
- var ctx = cc.context
- var in_expr, err = cc.checkChildExpr(nil, in)
- if err != nil { return nil, err }
- var in_t = in_expr.Type
- if record, def, args, ok := getRecord(in_t.Type, ctx); ok {
- if field_index, ok := record.FieldIndexMap[key]; ok {
- var field = record.FieldList[field_index]
- var field_t_ = inflateFieldType(field, def, args)
- var field_t = typsys.CertainType { Type: field_t_ }
- return cc.assign(field_t, loc,
- program.FieldValue {
- Record: in_expr,
- Index: field_index,
- })
- }}
- if inner_t_, ok := program.T_Observable_(in_t.Type); ok {
- if record, def, args, ok := getRecord(inner_t_, ctx); ok {
- if field_index, ok := record.FieldIndexMap[key]; ok {
- var field = record.FieldList[field_index]
- var field_t_ = inflateFieldType(field, def, args)
- var field_ob_t_ = program.T_Observable(field_t_)
- var field_ob_t = typsys.CertainType { Type: field_ob_t_ }
- return cc.assign(field_ob_t, loc,
- program.ObservableFieldProjection {
- Base: in_expr,
- Index: field_index,
- })
- }}}
- if method_t, f, index, path, ok := ctx.resolveMethod(in_t, key, nil); ok {
- if f != nil {
- return cc.assign(method_t, loc,
- program.ConcreteMethodValue {
- Location: loc,
- This: in_expr,
- Path: path,
- Method: f,
- })
- } else {
- return cc.assign(method_t, loc,
- program.AbstractMethodValue {
- Location: loc,
- Interface: in_expr,
- Path: path,
- Index: index,
- })
- }
- }
- return cc.error(loc,
- E_NoSuchFieldOrMethod {
- FieldName: key,
- TypeDesc: typsys.DescribeCertain(in_t),
- })
- }
- func checkPipeInterior(interior ast.PipeInterior, in ast.Expr, cc *exprCheckContext) (*program.Expr, *source.Error) {
- var ref = getRef(interior.RefBase)
- var loc = interior.Location
- var ctx = cc.context
- var in_expr, err = cc.checkChildExpr(nil, in)
- if err != nil { return nil, err }
- var in_t = in_expr.Type
- if ref.Namespace == "" {
- var key = ref.ItemName
- if r, d, a, o, b, ok := getInteriorReferableRecord(in_t, ctx); ok {
- var index, exists = r.FieldIndexMap[key]
- if !(exists) { goto NG }
- var field = r.FieldList[index]
- var field_t_ = inflateFieldType(field, d, a)
- var lens1_t_ = program.T_Lens1(b.Type, field_t_)
- var lens1_t = typsys.CertainType { Type: lens1_t_}
- return cc.assign(lens1_t, loc,
- program.InteriorRef {
- Base: in_expr,
- Index: index,
- Kind: program.RK_RecordField,
- Operand: o,
- })
- }
- if e, o, b, ok := getInteriorReferableEnum(in_t, ctx); ok {
- var index, exists = e.FieldIndexMap[key]
- if !(exists) { goto NG }
- var null_t = program.T_Null()
- var lens2_t_ = program.T_Lens2(b.Type, null_t)
- var lens2_t = typsys.CertainType { Type: lens2_t_ }
- return cc.assign(lens2_t, loc,
- program.InteriorRef {
- Base: in_expr,
- Index: index,
- Kind: program.RK_EnumItem,
- Operand: o,
- })
- }
- if u, d, a, o, b, ok := getInteriorReferableUnion(in_t, ctx); ok {
- var index, exists = u.FieldIndexMap[key]
- if !(exists) { goto NG }
- var field = u.FieldList[index]
- var field_t_ = inflateFieldType(field, d, a)
- var lens2_t_ = program.T_Lens2(b.Type, field_t_)
- var lens2_t = typsys.CertainType { Type: lens2_t_ }
- return cc.assign(lens2_t, loc,
- program.InteriorRef {
- Base: in_expr,
- Index: index,
- Kind: program.RK_UnionItem,
- Operand: o,
- })
- }
- }
- if _, I, a, o, b, ok := getInteriorReferableInterface(in_t, ctx); ok {
- var C, exists = ctx.resolveType(ref)
- if !(exists) { goto NG }
- var _, is_interface = C.Content.(typsys.Interface)
- if is_interface { goto NG }
- var table, ok = ctx.resolveDispatchTable(C, I)
- if !(ok) { goto NG }
- var base_type = b.Type
- var concrete_type = typsys.RefType { Def: C.Ref, Args: a }
- var lens2_t_ = program.T_Lens2(base_type, concrete_type)
- var lens2_t = typsys.CertainType { Type: lens2_t_ }
- return cc.assign(lens2_t, loc,
- program.InteriorRef {
- Base: in_expr,
- Table: table,
- Kind: program.RK_DynamicCast,
- Operand: o,
- })
- }
- NG:
- return cc.error(loc,
- E_InteriorRefUnavailable {
- InteriorRef: ref.String(),
- TypeDesc: typsys.DescribeCertain(in_t),
- })
- }
- func checkPipeInfix(infix ast.PipeInfix, in ast.Expr, cc *exprCheckContext) (*program.Expr, *source.Error) {
- if infix.Off {
- return cc.forwardTo(in)
- }
- var left, err = cc.checkChildExpr(nil, in)
- if err != nil { return nil, err }
- var right = infix.PipeCall
- var op = infix.Callee
- var loc = infix.Location
- return checkCallFunRef(op, left, right, true, loc, cc)
- }
- func checkInfixTerm(I ast.InfixTerm, cc *exprCheckContext) (*program.Expr, *source.Error) {
- var left, err = cc.checkChildExpr(nil, I.Left)
- if err != nil { return nil, err }
- var right = craftInfixRight(I.Right, I.Node)
- var op = I.Operator
- var loc = I.Location
- return checkCallFunRef(op, left, right, true, loc, cc)
- }
- func checkPipeCall(args ast.VariousPipeCall, callee ast.Expr, cc *exprCheckContext) (*program.Expr, *source.Error) {
- var loc = callee.Location
- if ref_node, tag, is_new, is_ref := ast.GetStandaloneRef(callee); is_ref {
- if is_new {
- return checkNewRecord(ref_node, args, tag, loc, cc)
- } else {
- var ctx = cc.context
- var ref = getRef(ref_node.Base)
- if ((ref.Namespace == "") && ctx.hasBinding(ref.ItemName)) {
- return checkCallExpr(callee, args, cc)
- } else {
- return checkCallFunRef(ref_node, nil, args, false, loc, cc)
- }
- }
- } else {
- return checkCallExpr(callee, args, cc)
- }
- }
|