diff --git a/ssa/abi/abi.go b/ssa/abi/abi.go index 4841b895..28e065b3 100644 --- a/ssa/abi/abi.go +++ b/ssa/abi/abi.go @@ -159,6 +159,10 @@ func (b *Builder) TypeName(t types.Type) (ret string, pub bool) { return "_llgo_any", true } return b.InterfaceName(t) + case *types.Map: + key, pub1 := b.TypeName(t.Key()) + elem, pub2 := b.TypeName(t.Elem()) + return fmt.Sprintf("map[%s]%s", key, elem), pub1 && pub2 } log.Panicf("todo: %T\n", t) return diff --git a/ssa/datastruct.go b/ssa/datastruct.go index aa09b8c0..819e6d21 100644 --- a/ssa/datastruct.go +++ b/ssa/datastruct.go @@ -365,3 +365,50 @@ func (b Builder) MapUpdate(m, k, v Expr) { } // ----------------------------------------------------------------------------- + +// The Range instruction yields an iterator over the domain and range +// of X, which must be a string or map. +// +// Elements are accessed via Next. +// +// Type() returns an opaque and degenerate "rangeIter" type. +// +// Pos() returns the ast.RangeStmt.For. +// +// Example printed form: +// +// t0 = range "hello":string +func (b Builder) Range(x Expr) Expr { + switch x.kind { + case vkString: + return b.InlineCall(b.Pkg.rtFunc("NewStringIter"), x) + } + panic("todo") +} + +// The Next instruction reads and advances the (map or string) +// iterator Iter and returns a 3-tuple value (ok, k, v). If the +// iterator is not exhausted, ok is true and k and v are the next +// elements of the domain and range, respectively. Otherwise ok is +// false and k and v are undefined. +// +// Components of the tuple are accessed using Extract. +// +// The IsString field distinguishes iterators over strings from those +// over maps, as the Type() alone is insufficient: consider +// map[int]rune. +// +// Type() returns a *types.Tuple for the triple (ok, k, v). +// The types of k and/or v may be types.Invalid. +// +// Example printed form: +// +// t1 = next t0 +func (b Builder) Next(iter Expr, isString bool) (ret Expr) { + if isString { + return b.InlineCall(b.Pkg.rtFunc("StringIterNext"), iter) + } + panic("todo") +} + +// ----------------------------------------------------------------------------- diff --git a/ssa/expr.go b/ssa/expr.go index 7c0c3155..6b58f08a 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -742,53 +742,6 @@ func castPtr(b llvm.Builder, x llvm.Value, t llvm.Type) llvm.Value { // ----------------------------------------------------------------------------- -// The Range instruction yields an iterator over the domain and range -// of X, which must be a string or map. -// -// Elements are accessed via Next. -// -// Type() returns an opaque and degenerate "rangeIter" type. -// -// Pos() returns the ast.RangeStmt.For. -// -// Example printed form: -// -// t0 = range "hello":string -func (b Builder) Range(x Expr) Expr { - switch x.kind { - case vkString: - return b.InlineCall(b.Pkg.rtFunc("NewStringIter"), x) - } - panic("todo") -} - -// The Next instruction reads and advances the (map or string) -// iterator Iter and returns a 3-tuple value (ok, k, v). If the -// iterator is not exhausted, ok is true and k and v are the next -// elements of the domain and range, respectively. Otherwise ok is -// false and k and v are undefined. -// -// Components of the tuple are accessed using Extract. -// -// The IsString field distinguishes iterators over strings from those -// over maps, as the Type() alone is insufficient: consider -// map[int]rune. -// -// Type() returns a *types.Tuple for the triple (ok, k, v). -// The types of k and/or v may be types.Invalid. -// -// Example printed form: -// -// t1 = next t0 -func (b Builder) Next(iter Expr, isString bool) (ret Expr) { - if isString { - return b.InlineCall(b.Pkg.rtFunc("StringIterNext"), iter) - } - panic("todo") -} - -// ----------------------------------------------------------------------------- - // The MakeClosure instruction yields a closure value whose code is // Fn and whose free variables' values are supplied by Bindings. //