kpmy 9 years ago
parent
commit
69cebe5161
11 changed files with 351 additions and 0 deletions
  1. 13 0
      LICENSE
  2. 12 0
      demo0.wasm
  3. 81 0
      docu/proto.md
  4. 1 0
      dump.wasm
  5. 14 0
      gen/generator.go
  6. 14 0
      gen/impl/impl.go
  7. 107 0
      gen/impl/sexpr/sexpr.go
  8. 79 0
      ir/ast.go
  9. 1 0
      test0.wasm
  10. 5 0
      tiss.go
  11. 24 0
      tiss_test.go

+ 13 - 0
LICENSE

@@ -0,0 +1,13 @@
+           DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+                   Version 2, December 2004
+
+Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
+
+Everyone is permitted to copy and distribute verbatim or modified
+copies of this license document, and changing it is allowed as long
+as the name is changed.
+
+           DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+  TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. You just DO WHAT THE FUCK YOU WANT TO.

+ 12 - 0
demo0.wasm

@@ -0,0 +1,12 @@
+;; my little module 
+(module 
+	(memory 0 0)
+	(func $start
+		(call_import $print (call $get))
+		(call_import $print (i64.extend_u/i32 (memory_size)))
+	)
+	(import $print "spectest" "print" (param i64))
+	(func $get (result i64) (nop) (return (i64.const 1)))
+	
+	(start $start)
+)

+ 81 - 0
docu/proto.md

@@ -0,0 +1,81 @@
+# tiss lang concepts
+
+### assignments, variables, objects
+
+````
+hash -> a
+5 -> x
+10 + x -> y
+m[10] -> y
+h["hash"] -> x
+h.hash
+````
+
+### expressions
+
+````
+(x + 5) ^ (4 + x)
+x // 2
+x % 2
+x / 2.3
+x + 1
+-x
+!(-x)
+1 -! x
+1 +! x
+3 - 3
+e = 1
+3 # e
+[1 .. 4)
+(-inf .. inf)
+````
+
+### selectors
+
+````
+x[4].block.x[5].y -> z
+x[1 .. 4] -> x14
+````
+
+### blocks
+````
+BLOCK
+
+END
+
+BLOCK Block
+
+END Block
+
+BLOCK
+
+END -> block
+````
+
+### versioning
+````
+UNIT Unit
+VERSION 0.0.0
+
+  IMPORT OtherUnit[2.3.4]  
+
+INIT
+
+CLOSE
+
+END Unit
+````
+
+### statements
+
+````
+0 -> i
+Block
+Block(i, x, ret)
+Block[0 -> x, ret -> z]
+\Block 0 -> i
+IF x THEN 0 -> i ELSIF ~x THEN 1 -> i ELSE -1 -> i END
+WHILE x DO INC(i) END
+REPEAT INC(i) UNTIL x;
+CHOOSE x OF 1: Block1 OR 2: Block2 ELSE BlockElse END
+````

+ 1 - 0
dump.wasm

@@ -0,0 +1 @@
+(module (start $start))

+ 14 - 0
gen/generator.go

@@ -0,0 +1,14 @@
+package gen //import "github.com/kpmy/tiss/gen"
+
+import (
+	"io"
+
+	"github.com/kpmy/tiss/ir"
+)
+
+type Writer interface {
+	WriteExpr(ir.Expression) error
+	WriteValue(interface{}) error
+}
+
+var NewWriter func(io.Writer) Writer

+ 14 - 0
gen/impl/impl.go

@@ -0,0 +1,14 @@
+package impl
+
+import (
+	"io"
+
+	"github.com/kpmy/tiss/gen"
+	"github.com/kpmy/tiss/gen/impl/sexpr"
+)
+
+func init() {
+	gen.NewWriter = func(w io.Writer) gen.Writer {
+		return sexpr.New(w)
+	}
+}

+ 107 - 0
gen/impl/sexpr/sexpr.go

@@ -0,0 +1,107 @@
+package sexpr
+
+import (
+	"io"
+	"reflect"
+	"strings"
+	"unicode"
+
+	"github.com/kpmy/tiss/gen"
+	"github.com/kpmy/tiss/ir"
+	"github.com/kpmy/ypk/fn"
+	. "github.com/kpmy/ypk/tc"
+)
+
+const InvalidAtom Error = "invalid name of atom"
+
+const NameTag = "sexpr"
+
+type wr struct {
+	base io.Writer
+}
+
+func (w *wr) Raw(s string) {
+	if _, err := w.base.Write([]byte(s)); err != nil {
+		panic(err)
+	}
+}
+
+const invalidAtomChars = ""
+
+func validateAtomString(s string) {
+	if strings.ContainsAny(s, invalidAtomChars) {
+		panic(InvalidAtom)
+	} else {
+		r := []rune(s)
+		for i := 0; i < len(r); i++ {
+			Assert(!unicode.IsSpace(r[i]), 20, InvalidAtom)
+		}
+	}
+}
+
+func (w *wr) Atom(_v interface{}) {
+	switch v := _v.(type) {
+	case string:
+		Assert(v != "", 20)
+		validateAtomString(v)
+		w.Raw(v)
+	case ir.Variable:
+		w.Atom(v.ValueOf())
+	default:
+		Halt(100, "wrong atom ", reflect.TypeOf(v))
+	}
+}
+
+func getName(i interface{}) (ret string) {
+	t := reflect.ValueOf(i).Elem().Type()
+	for i := 0; i < t.NumField() && ret == ""; i++ {
+		s := t.Field(i)
+		ret = s.Tag.Get(NameTag)
+	}
+	return
+}
+
+func (w *wr) WriteValue(v interface{}) (err error) {
+	Try(func(x ...interface{}) (ret interface{}) {
+		x0 := x[0]
+		switch v := x0.(type) {
+		case ir.Expression:
+			err = w.WriteExpr(v)
+		default:
+			w.Atom(x0)
+		}
+		return
+	}, v).Catch(nil, func(e error) {
+		err = e
+	}).Do()
+	return
+}
+
+func (w *wr) WriteExpr(e ir.Expression) (err error) {
+	Assert(!fn.IsNil(e), 20)
+	if err = e.Validate(); err == nil {
+		Do(func() {
+			w.Raw("(")
+			w.Atom(getName(e))
+			if n, ok := e.(ir.Node); ok {
+				if el := n.Children(); len(el) > 0 {
+					for _, _e := range el {
+						w.Raw(" ")
+						if err = w.WriteValue(_e); err != nil {
+							panic(err)
+						}
+					}
+				}
+			}
+			w.Raw(")")
+		}).Catch(nil, func(e error) {
+			err = e
+		}).Do()
+	}
+	return err
+}
+
+func New(w io.Writer) gen.Writer {
+	Assert(!fn.IsNil(w), 20)
+	return &wr{base: w}
+}

+ 79 - 0
ir/ast.go

@@ -0,0 +1,79 @@
+package ir //import "github.com/kpmy/tiss/ir"
+
+import (
+	"reflect"
+
+	"github.com/kpmy/ypk/fn"
+	. "github.com/kpmy/ypk/tc"
+)
+
+type Expression interface {
+	Validate() error
+}
+
+type Node interface {
+	Children() []interface{}
+}
+
+type ns struct{}
+
+type Variable struct {
+	sv *string
+	iv *int
+}
+
+func ThisVariable(_x interface{}) (ret Variable) {
+	switch x := _x.(type) {
+	case string:
+		Assert(x[0] == '$', 20)
+		ret.sv = &x
+	case int:
+		ret.iv = &x
+	default:
+		Halt(100, reflect.TypeOf(x))
+	}
+	return
+}
+
+func (v Variable) IsEmpty() bool {
+	return fn.IsNil(v.iv) && fn.IsNil(v.sv)
+}
+
+func (v Variable) ValueOf() (ret interface{}) {
+	if !fn.IsNil(v.sv) {
+		ret = *v.sv
+	} else if !fn.IsNil(v.iv) {
+		ret = *v.iv
+	}
+	return
+}
+
+type StartExpr struct {
+	ns  `sexpr:"start"`
+	Var Variable
+}
+
+func (s *StartExpr) Validate() (err error) {
+	if s.Var.IsEmpty() {
+		err = Error("empty start variable")
+	}
+	return
+}
+
+func (s *StartExpr) Children() (ret []interface{}) {
+	return []interface{}{s.Var}
+}
+
+type Module struct {
+	ns    `sexpr:"module"`
+	Start *StartExpr
+}
+
+func (m *Module) Children() (ret []interface{}) {
+	ret = append(ret, m.Start)
+	return
+}
+
+func (m *Module) Validate() (err error) {
+	return
+}

+ 1 - 0
test0.wasm

@@ -0,0 +1 @@
+(module)

+ 5 - 0
tiss.go

@@ -0,0 +1,5 @@
+package tiss
+
+import (
+	_ "github.com/kpmy/tiss/gen/impl"
+)

+ 24 - 0
tiss_test.go

@@ -0,0 +1,24 @@
+package tiss
+
+import (
+	"os"
+	"testing"
+
+	"github.com/kpmy/tiss/gen"
+	"github.com/kpmy/tiss/ir"
+)
+
+func TestDump(t *testing.T) {
+	if f, err := os.Create("dump.wasm"); err == nil {
+		defer f.Close()
+		m := &ir.Module{}
+		m.Start = &ir.StartExpr{Var: ir.ThisVariable("$start")}
+		if err = gen.NewWriter(f).WriteExpr(m); err == nil {
+
+		} else {
+			t.Error(err)
+		}
+	} else {
+		t.Error(err)
+	}
+}