diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs index b922b3780ed..89a19fc237b 100644 --- a/src/comp/front/creader.rs +++ b/src/comp/front/creader.rs @@ -6,11 +6,14 @@ import lib.llvm.llvmext; import lib.llvm.mk_object_file; import lib.llvm.mk_section_iter; import middle.fold; +import middle.ty; import util.common; import util.common.span; import std._str; +import std._vec; import std.fs; +import std.option; import std.os; import std.map.hashmap; @@ -20,6 +23,174 @@ type env = @rec( vec[str] library_search_paths ); +// Type decoding + +// Compact string representation for ty.t values. API ty_str & parse_from_str. +// (The second has to be authed pure.) Extra parameters are for converting +// to/from def_ids in the string rep. Whatever format you choose should not +// contain pipe characters. + +// Callback to translate defs to strs or back. +type str_def = fn(str) -> ast.def_id; + +type pstate = rec(str rep, mutable uint pos, uint len); + +fn peek(@pstate st) -> char { + if (st.pos < st.len) {ret st.rep.(st.pos) as char;} + else {ret ' ';} +} +impure fn next(@pstate st) -> char { // ?? somehow not recognized as impure + if (st.pos >= st.len) {fail;} + auto ch = st.rep.(st.pos); + st.pos = st.pos + 1u; + ret ch as char; +} + +fn parse_ty_str(str rep, str_def sd) -> @ty.t { + auto len = _str.byte_len(rep); + auto st = @rec(rep=rep, mutable pos=0u, len=len); + auto result = parse_ty(st, sd); + check(st.pos == len); + ret result; +} + +impure fn parse_ty(@pstate st, str_def sd) -> @ty.t { + ret @rec(struct=parse_sty(st, sd), + cname=option.none[str]); +} + +impure fn parse_sty(@pstate st, str_def sd) -> ty.sty { + alt (next(st)) { + case ('n') {ret ty.ty_nil;} + case ('b') {ret ty.ty_bool;} + case ('i') {ret ty.ty_int;} + case ('u') {ret ty.ty_uint;} + case ('M') { + alt (next(st)) { + case ('b') {ret ty.ty_machine(common.ty_u8);} + case ('w') {ret ty.ty_machine(common.ty_u16);} + case ('l') {ret ty.ty_machine(common.ty_u32);} + case ('d') {ret ty.ty_machine(common.ty_u64);} + case ('B') {ret ty.ty_machine(common.ty_i8);} + case ('W') {ret ty.ty_machine(common.ty_i16);} + case ('L') {ret ty.ty_machine(common.ty_i32);} + case ('D') {ret ty.ty_machine(common.ty_i64);} + case ('f') {ret ty.ty_machine(common.ty_f32);} + case ('F') {ret ty.ty_machine(common.ty_f64);} + } + } + case ('c') {ret ty.ty_char;} + case ('s') {ret ty.ty_str;} + case ('t') { + check(next(st) == '['); + auto def = ""; + while (peek(st) != '|') {def += _str.from_char(next(st));} + st.pos = st.pos + 1u; + let vec[@ty.t] params = vec(); + while (peek(st) != ']') { + params = _vec.push[@ty.t](params, parse_ty(st, sd)); + } + st.pos = st.pos + 1u; + ret ty.ty_tag(sd(def), params); + } + case ('@') {ret ty.ty_box(parse_ty(st, sd));} + case ('V') {ret ty.ty_vec(parse_ty(st, sd));} + case ('P') {ret ty.ty_port(parse_ty(st, sd));} + case ('C') {ret ty.ty_chan(parse_ty(st, sd));} + case ('T') { + check(next(st) == '['); + let vec[@ty.t] params = vec(); + while (peek(st) != ']') { + params = _vec.push[@ty.t](params, parse_ty(st, sd)); + } + st.pos = st.pos + 1u; + ret ty.ty_tup(params); + } + case ('R') { + check(next(st) == '['); + let vec[ty.field] fields = vec(); + while (peek(st) != ']') { + auto name = ""; + while (peek(st) != '=') {name += _str.from_char(next(st));} + st.pos = st.pos + 1u; + fields = _vec.push[ty.field] + (fields, rec(ident=name, ty=parse_ty(st, sd))); + } + st.pos = st.pos + 1u; + ret ty.ty_rec(fields); + } + case ('F') { + auto func = parse_ty_fn(st, sd); + ret ty.ty_fn(ast.proto_fn, func._0, func._1); + } + case ('W') { + auto func = parse_ty_fn(st, sd); + ret ty.ty_fn(ast.proto_iter, func._0, func._1); + } + case ('N') { + auto abi; + alt (next(st)) { + case ('r') {abi = ast.native_abi_rust;} + case ('c') {abi = ast.native_abi_cdecl;} + } + auto func = parse_ty_fn(st, sd); + ret ty.ty_native_fn(abi,func._0,func._1); + } + case ('O') { + check(next(st) == '['); + let vec[ty.method] methods = vec(); + while (peek(st) != ']') { + auto proto; + alt (next(st)) { + case ('W') {proto = ast.proto_iter;} + case ('F') {proto = ast.proto_fn;} + } + auto name = ""; + while (peek(st) != '[') {name += _str.from_char(next(st));} + auto func = parse_ty_fn(st, sd); + methods = _vec.push[ty.method] + (methods, rec(proto=proto, + ident=name, + inputs=func._0, + output=func._1)); + } + ret ty.ty_obj(methods); + } + case ('X') {ret ty.ty_var(parse_int(st));} + case ('E') {ret ty.ty_native;} + } +} + +impure fn parse_int(@pstate st) -> int { + auto n = 0; + while (true) { + auto cur = peek(st); + if (cur < '0' || cur > '9') {break;} + st.pos = st.pos + 1u; + n *= 10; + n += (cur as int) - ('0' as int); + } + ret n; +} + +impure fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty.arg], @ty.t) { + check(next(st) == '['); + let vec[ty.arg] inputs = vec(); + while (peek(st) != ']') { + auto mode = ast.val; + if (peek(st) == '&') { + mode = ast.alias; + st.pos = st.pos + 1u; + } + inputs = _vec.push[ty.arg] + (inputs, rec(mode=mode, ty=parse_ty(st, sd))); + } + st.pos = st.pos + 1u; + ret tup(inputs, parse_ty(st, sd)); +} + + + // TODO: return something fn load_crate(ast.ident ident, vec[str] library_search_paths) -> @() { for (str library_search_path in library_search_paths) { diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs index 433d7147024..bff0ac94e19 100644 --- a/src/comp/middle/metadata.rs +++ b/src/comp/middle/metadata.rs @@ -1,12 +1,118 @@ import std._str; +import std._vec; +import std.option; + import front.ast; import middle.trans; +import middle.ty; import back.x86; +import util.common; import lib.llvm.llvm; import lib.llvm.llvm.ValueRef; import lib.llvm.False; +// Type encoding + +// Compact string representation for ty.t values. API ty_str & parse_from_str. +// (The second has to be authed pure.) Extra parameters are for converting +// to/from def_ids in the string rep. Whatever format you choose should not +// contain pipe characters. + +// Callback to translate defs to strs or back. +type def_str = fn(ast.def_id) -> str; + +fn ty_str(@ty.t t, def_str ds) -> str { + ret sty_str(t.struct, ds); +} + +fn sty_str(ty.sty st, def_str ds) -> str { + alt (st) { + case (ty.ty_nil) {ret "n";} + case (ty.ty_bool) {ret "b";} + case (ty.ty_int) {ret "i";} + case (ty.ty_uint) {ret "u";} + case (ty.ty_machine(?mach)) { + alt (mach) { + case (common.ty_u8) {ret "Mb";} + case (common.ty_u16) {ret "Mw";} + case (common.ty_u32) {ret "Ml";} + case (common.ty_u64) {ret "Md";} + case (common.ty_i8) {ret "MB";} + case (common.ty_i16) {ret "MW";} + case (common.ty_i32) {ret "ML";} + case (common.ty_i64) {ret "MD";} + case (common.ty_f32) {ret "Mf";} + case (common.ty_f64) {ret "MF";} + } + } + case (ty.ty_char) {ret "c";} + case (ty.ty_str) {ret "s";} + case (ty.ty_tag(?def,?tys)) { // TODO restore def_id + auto acc = "t[" + ds(def) + "|"; + for (@ty.t t in tys) {acc += ty_str(t, ds);} + ret acc + "]"; + } + case (ty.ty_box(?t)) {ret "@" + ty_str(t, ds);} + case (ty.ty_vec(?t)) {ret "V" + ty_str(t, ds);} + case (ty.ty_port(?t)) {ret "P" + ty_str(t, ds);} + case (ty.ty_chan(?t)) {ret "C" + ty_str(t, ds);} + case (ty.ty_tup(?tys)) { + auto acc = "T["; + for (@ty.t t in tys) {acc += ty_str(t, ds);} + ret acc + "]"; + } + case (ty.ty_rec(?fields)) { + auto acc = "R["; + for (ty.field field in fields) { + acc += field.ident + "="; + acc += ty_str(field.ty, ds); + } + ret acc + "]"; + } + case (ty.ty_fn(?proto,?args,?out)) { + ret proto_str(proto) + ty_fn_str(args, out, ds); + } + case (ty.ty_native_fn(?abi,?args,?out)) { + auto abistr; + alt (abi) { + case (ast.native_abi_rust) {abistr = "r";} + case (ast.native_abi_cdecl) {abistr = "c";} + } + ret "N" + abistr + ty_fn_str(args, out, ds); + } + case (ty.ty_obj(?methods)) { + auto acc = "O["; + for (ty.method m in methods) { + acc += proto_str(m.proto); + acc += m.ident; + acc += ty_fn_str(m.inputs, m.output, ds); + } + ret acc + "]"; + } + case (ty.ty_var(?id)) {ret "X" + common.istr(id);} + case (ty.ty_native) {ret "E";} + // TODO (maybe?) ty_param(ast.def_id), ty_type; + } +} + +fn proto_str(ast.proto proto) -> str { + alt (proto) { + case (ast.proto_iter) {ret "W";} + case (ast.proto_fn) {ret "F";} + } +} + +fn ty_fn_str(vec[ty.arg] args, @ty.t out, def_str ds) -> str { + auto acc = "["; + for (ty.arg arg in args) { + if (arg.mode == ast.alias) {acc += "&";} + acc += ty_str(arg.ty, ds); + } + ret acc + "]" + ty_str(out, ds); +} + + // Returns a Plain Old LLVM String. fn C_postr(str s) -> ValueRef { ret llvm.LLVMConstString(_str.buf(s), _str.byte_len(s), False);