def List(env: Env, t, out): ty = ts.Type() out.append('[') for sub in t: ty = check(ty, env, sub, out, '全ての要素を同じ型に揃えてください') out.append(',') out.append(']') return ts.Type(f'list[{ty}]')
def ApplyExpr(env: Env, t, out): name = str(t['name']) if name in env: vari = env[name] name = vari.target types = vari.types if name == 'world': set_World(env, t, types[-1]) return ts.Matter elif t['name'].tag == 'NLPSymbol': name, types = checkNLPMatter(env, name, t) else: perror(env, t['name'], f'タイプミス? {name} 未定義な関数名です') return ts.Type() # To avoid error if ts.isMatterFunc(types): with Env(env) as env: out.append(f'puppy.new_(puppy.vars["{name}"],') args = [x for x in t] emitArguments(env, t['name'], args, types, '', out) env['@@yield'] = trace(env, t) env['@@oid'] += 1 else: out.append(name) out.append('(') args = [x for x in t] emitArguments(env, t['name'], args, types, '', out) if name == 'puppy.print': env['@@yield'] = trace(env, t) env['@@oid'] += 1 return types[0]
def VarDecl(env: Env, t, out): left = t['left'] newvar = None ty = None if left.tag == 'Name': name = str(left) if name in env: vari = env[name] ty = vari.types out.append(vari.target) elif '@local' in env: # ローカルスコープなら newvar = localName(name) out.append(f'var {newvar}') else: newvar = globalName(name) out.append(newvar) else: ty = conv(env, t['left'], out) out.append(' = ') # 左辺値から型推論する if ty is None: ty = ts.Type() ty = check(ty, env, t['right'], out) if newvar != None: env[name] = Symbol(newvar, mutable, ty) return ts.Void
def conv(env: Env, t, out): if t.tag in func: return func[t.tag](env, t, out) else: perror(env, t, f'未実装のコード{t.tag}です。') print('@Debug[conv]', str(t), t) out.append('undefined') return ts.Type()
def Name(env: Env, t, out): name = str(t) if name in env: var = env[name] out.append(var.target) return var.types else: out.append(name) perror(env, t, f'変数名 {name} は一度も定義されていません') return ts.Type()
def FuncExpr(env: Env, t, out): with Env(env) as lenv: types = [ts.Type()] voidCheck = str(types[0]) out.append("(") for p in t['params']: pname = str(p) ty = ts.Type() if (len(types) > 1): out.append(f',{pname}') else: out.append(pname) types.append(ty) lenv[pname] = Symbol(localName(pname), mutable, ty) out.append(") => ") lenv['@local'] = types[0] # return type conv(lenv, t['body'], out) if voidCheck == str(types[0]): types[0] = ts.Void return tuple(types)
def GetExpr(env: Env, t, out): name = str(t['name']) pkgname = str(t['recv']) + '.' if pkgname in env: # math.pi のような定数 penv = env[pkgname] if name in penv: vari = penv[name] out.append(vari.target) return vari.types else: perror(env, t['name'], f'{pkgname}{name}? タイプミスしてませんか?') out.append('undefined') return ts.Type() check(ts.Matter, env, t['recv'], out) out.append('.') if not name in KEYWORDS: pwarn(env, t['name'], f'{name}? タイプミスしてませんか?') out.append(name) return ts.Type() else: name = KEYWORDS[name] out.append(name) return ts.newType(KEYWORDTYPES[name])
def FuncDecl(env: Env, t, out): name = str(t['name']) jsname = emitDeclName(env, name, out) with Env(env) as lenv: types = [ts.Type()] voidCheck = str(types[0]) out.append('(') for p in t['params']: pname = str(p['name']) if (len(types) > 1): out.append(f',{pname}') else: out.append(pname) ty = ts.parseOf(p['type'], pwarn) if 'type' in p else ts.Type() types.append(ty) lenv[pname] = Symbol(localName(pname), mutable, ty) out.append(") => ") lenv['@local'] = types[0] # return type env[name] = Symbol(jsname, mutable, tuple(types)) conv(lenv, t['body'], out) if voidCheck == str(types[0]): types[0] = ts.Void return ts.Void
def ForStmt(env: Env, t, out): if (t['each'].tag == 'Name'): name = str(t['each']) else: perror(env, t['each'], '変数名が欲しいところです') return ts.Void out.append(f'for (let {name} of ') ty = check(ts.Type('list[__]'), env, t['list'], out, msg='ここはリストでなければなりません') out.append(')') ty = ts.typeOfSeq(ty) with Env(env) as env: env[name] = Symbol(localName(name), True, ty) env['inloop'] = True conv(env, t['body'], out) return ts.Void
def ForStmt(env, t, out): if (t['each'].tag == 'Name'): name = t['each'].asString() else: perror(env, t['each'], '変数名が欲しいところです') return ts.Void out.append(f'for (let {name} of ') ty = check(ts.Type('list[__]'), env, t['list'], out, msg='ここはリストでなければなりません') out.append(')') ty = ts.typeOfSeq(ty) outer = pushenv(env, name, Symbol(localName(name), True, ty)) outer2 = pushenv(env, '@inloop', True) conv(env, t['body'], out) popenv(env, name, outer) popenv(env, '@inloop', outer2) return ts.Void
def emitUndefined(env: Env, t, out): out.append('undefined') return ts.Type()