コード例 #1
0
ファイル: misc.go プロジェクト: IanMurray/ark
func CapitalizeFirst(s string) string {
	runes := []rune(s)

	runes[0] = unicode.ToTitle(runes[0])

	return string(runes)
}
コード例 #2
0
ファイル: example_test.go プロジェクト: RajibTheKing/gcc
func ExampleToTitle() {
	const ucG = 'g'
	fmt.Printf("%#U\n", unicode.ToTitle(ucG))

	// Output:
	// U+0047 'G'
}
コード例 #3
0
ファイル: context_test.go プロジェクト: rawlingsj/gofabric8
func TestWordBreaks(t *testing.T) {
	for _, tt := range breakTest {
		testtext.Run(t, tt, func(t *testing.T) {
			parts := strings.Split(tt, "|")
			want := ""
			for _, s := range parts {
				found := false
				// This algorithm implements title casing given word breaks
				// as defined in the Unicode standard 3.13 R3.
				for _, r := range s {
					title := unicode.ToTitle(r)
					lower := unicode.ToLower(r)
					if !found && title != lower {
						found = true
						want += string(title)
					} else {
						want += string(lower)
					}
				}
			}
			src := strings.Join(parts, "")
			got := Title(language.Und).String(src)
			if got != want {
				t.Errorf("got %q; want %q", got, want)
			}
		})
	}
}
コード例 #4
0
ファイル: main.go プロジェクト: TomHoenderdos/go-sunos
func capitalize(s string) string {
	if s == "" {
		return s
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToTitle(r)) + s[n:]
}
コード例 #5
0
ファイル: context_test.go プロジェクト: msoap/html2data
func TestMapping(t *testing.T) {
	assigned := rangetable.Assigned(UnicodeVersion)
	coreVersion := rangetable.Assigned(unicode.Version)
	if coreVersion == nil {
		coreVersion = assigned
	}
	apply := func(r rune, f func(c *context) bool) string {
		c := contextFromRune(r)
		f(c)
		return string(c.dst[:c.pDst])
	}

	for r, tt := range special {
		if got, want := apply(r, lower), tt.toLower; got != want {
			t.Errorf("lowerSpecial:(%U): got %+q; want %+q", r, got, want)
		}
		if got, want := apply(r, title), tt.toTitle; got != want {
			t.Errorf("titleSpecial:(%U): got %+q; want %+q", r, got, want)
		}
		if got, want := apply(r, upper), tt.toUpper; got != want {
			t.Errorf("upperSpecial:(%U): got %+q; want %+q", r, got, want)
		}
	}

	for r := rune(0); r <= lastRuneForTesting; r++ {
		if !unicode.In(r, assigned) || !unicode.In(r, coreVersion) {
			continue
		}
		if rf := unicode.SimpleFold(r); rf == r || !unicode.In(rf, assigned) {
			continue
		}
		if _, ok := special[r]; ok {
			continue
		}
		want := string(unicode.ToLower(r))
		if got := apply(r, lower); got != want {
			t.Errorf("lower:%q (%U): got %q %U; want %q %U", r, r, got, []rune(got), want, []rune(want))
		}

		want = string(unicode.ToUpper(r))
		if got := apply(r, upper); got != want {
			t.Errorf("upper:%q (%U): got %q %U; want %q %U", r, r, got, []rune(got), want, []rune(want))
		}

		want = string(unicode.ToTitle(r))
		if got := apply(r, title); got != want {
			t.Errorf("title:%q (%U): got %q %U; want %q %U", r, r, got, []rune(got), want, []rune(want))
		}
	}
}
コード例 #6
0
ファイル: fasta.go プロジェクト: ndaniels/io-1
// TranslateNormal is the default translator for regular (NOT aligned) FASTA
// files.
func TranslateNormal(b byte) (seq.Residue, bool) {
	switch {
	case b >= 'a' && b <= 'z':
		return seq.Residue(unicode.ToTitle(rune(b))), true
	case b >= 'A' && b <= 'Z':
		return seq.Residue(b), true
	case b == '*':
		return 0, true
	case b == '-':
		return '-', true
	case b == '/': // PIR junk. Chain breaks? WTF?
		return '-', true
	}
	return 0, false
}
コード例 #7
0
ファイル: util.go プロジェクト: ccherng/gogl
// Converts strings with underscores to Go-like names. e.g.: bla_blub_foo -> BlaBlubFoo
func GoName(n string) string {
	prev := '_'
	return strings.Map(func(r rune) rune {
		if r == '_' {
			prev = r
			return -1
		}
		if prev == '_' {
			prev = r
			return unicode.ToTitle(r)
		}
		prev = r
		return unicode.ToLower(r)
	},
		n)
}
コード例 #8
0
ファイル: strings.go プロジェクト: aubonbeurre/gcc
// Title returns a copy of the string s with all Unicode letters that begin words
// mapped to their title case.
func Title(s string) string {
	// Use a closure here to remember state.
	// Hackish but effective. Depends on Map scanning in order and calling
	// the closure once per rune.
	prev := rune(' ')
	return Map(
		func(r rune) rune {
			if isSeparator(prev) {
				prev = r
				return unicode.ToTitle(r)
			}
			prev = r
			return r
		},
		s)
}
コード例 #9
0
// Title returns a copy of s with all Unicode letters that begin words
// mapped to their title case.
func Title(s []byte) []byte {
	// Use a closure here to remember state.
	// Hackish but effective. Depends on Map scanning in order and calling
	// the closure once per rune.
	prev := ' '
	return Map(
		func(r int) int {
			if isSeparator(prev) {
				prev = r
				return unicode.ToTitle(r)
			}
			prev = r
			return r
		},
		s)
}
コード例 #10
0
func fullCaseTest() {
	for i, c := range chars {
		lower := unicode.ToLower(i);
		want := caseIt(i, c.lowerCase);
		if lower != want {
			fmt.Fprintf(os.Stderr, "lower U+%04X should be U+%04X is U+%04X\n", i, want, lower)
		}
		upper := unicode.ToUpper(i);
		want = caseIt(i, c.upperCase);
		if upper != want {
			fmt.Fprintf(os.Stderr, "upper U+%04X should be U+%04X is U+%04X\n", i, want, upper)
		}
		title := unicode.ToTitle(i);
		want = caseIt(i, c.titleCase);
		if title != want {
			fmt.Fprintf(os.Stderr, "title U+%04X should be U+%04X is U+%04X\n", i, want, title)
		}
	}
}
コード例 #11
0
ファイル: ghaml.go プロジェクト: rayleyva/ghaml
// Gets a proper case for a string (i.e. capitalised like a proper noun)
func getProperCase(s string) string {
	// Generously 'borrowing' from strings.Map

	// In the worst case, the string can grow when mapped, making
	// things unpleasant.  But it's so rare we barge in assuming it's
	// fine.  It could also shrink but that falls out naturally.
	maxbytes := len(s) // length of b
	nbytes := 0        // number of bytes encoded in b
	var b []byte = make([]byte, maxbytes)

	needsCapitalising := true

	for _, c := range s {
		r := c

		// chars to skip and be followed by capitalisation
		if r == '.' || r == '-' || r == '_' || r == ' ' {
			needsCapitalising = true
			continue
		}

		if needsCapitalising {
			r = unicode.ToTitle(r)
			needsCapitalising = false
		}

		if r >= 0 {
			wid := 1
			if r >= utf8.RuneSelf {
				wid = utf8.RuneLen(r)
			}
			if nbytes+wid > maxbytes {
				// Grow the buffer.
				maxbytes = maxbytes*2 + utf8.UTFMax
				nb := make([]byte, maxbytes)
				copy(nb, b[0:nbytes])
				b = nb
			}
			nbytes += utf8.EncodeRune(b[nbytes:maxbytes], r)
		}
	}
	return string(b[0:nbytes])
}
コード例 #12
0
ファイル: maketables.go プロジェクト: 2thetop/go
func fullCaseTest() {
	for j, c := range chars {
		i := rune(j)
		lower := unicode.ToLower(i)
		want := caseIt(i, c.lowerCase)
		if lower != want {
			fmt.Fprintf(os.Stderr, "lower %U should be %U is %U\n", i, want, lower)
		}
		upper := unicode.ToUpper(i)
		want = caseIt(i, c.upperCase)
		if upper != want {
			fmt.Fprintf(os.Stderr, "upper %U should be %U is %U\n", i, want, upper)
		}
		title := unicode.ToTitle(i)
		want = caseIt(i, c.titleCase)
		if title != want {
			fmt.Fprintf(os.Stderr, "title %U should be %U is %U\n", i, want, title)
		}
	}
}
コード例 #13
0
ファイル: context_test.go プロジェクト: TriangleGo/golang.org
func TestMapping(t *testing.T) {
	apply := func(r rune, f func(c *context) bool) string {
		c := contextFromRune(r)
		f(c)
		return string(c.dst[:c.pDst])
	}

	for r, tt := range special {
		if got, want := apply(r, lower), tt.toLower; got != want {
			t.Errorf("lowerSpecial:(%U): got %+q; want %+q", r, got, want)
		}
		if got, want := apply(r, title), tt.toTitle; got != want {
			t.Errorf("titleSpecial:(%U): got %+q; want %+q", r, got, want)
		}
		if got, want := apply(r, upper), tt.toUpper; got != want {
			t.Errorf("upperSpecial:(%U): got %+q; want %+q", r, got, want)
		}
	}

	for r := rune(0); r <= lastRuneForTesting; r++ {
		if _, ok := special[r]; ok {
			continue
		}
		want := string(unicode.ToLower(r))
		if got := apply(r, lower); got != want {
			t.Errorf("lower:%q (%U): got %q %U; want %q %U", r, r, got, []rune(got), want, []rune(want))
		}

		want = string(unicode.ToUpper(r))
		if got := apply(r, upper); got != want {
			t.Errorf("upper:%q (%U): got %q %U; want %q %U", r, r, got, []rune(got), want, []rune(want))
		}

		want = string(unicode.ToTitle(r))
		if got := apply(r, title); got != want {
			t.Errorf("title:%q (%U): got %q %U; want %q %U", r, r, got, []rune(got), want, []rune(want))
		}
	}
}
コード例 #14
0
ファイル: bin2go.go プロジェクト: chsc/bin2go
func camelCase(s string) string {
	camel := false
	first := true
	return strings.Map(func(r rune) rune {
		if unicode.IsLetter(r) || unicode.IsDigit(r) {
			if first { // always lower case first rune
				first = false
				return unicode.ToLower(r)
			}
			if camel {
				camel = false
				return unicode.ToTitle(r)
			}
			return r
		}

		if !first { // if first runes aren't letters or digits, don't capitalize
			camel = true // unknown rune type -> ignore and title case next rune
		}

		return -1
	}, s)
}
コード例 #15
0
ファイル: error.go プロジェクト: fzerorubigd/go-dberror
// capitalize the first letter in the string
func capitalize(s string) string {
	r, size := utf8.DecodeRuneInString(s)
	return fmt.Sprintf("%c", unicode.ToTitle(r)) + s[size:]
}
コード例 #16
0
ファイル: color.go プロジェクト: dashaus/ark
func CapitalizeFirst(s string) string {
	return string(unicode.ToTitle([]rune(s)[0])) + s[1:]
}
コード例 #17
0
ファイル: hacker.go プロジェクト: go-gophers/gophers
func capitalize(s string) string {
	return string(unicode.ToTitle(rune(s[0]))) + s[1:]
}
コード例 #18
0
ファイル: types.go プロジェクト: kevinburke/twilio-go
// capitalize the first letter in s
func capitalize(s string) string {
	r, l := utf8.DecodeRuneInString(s)
	b := make([]byte, l)
	utf8.EncodeRune(b, unicode.ToTitle(r))
	return strings.Join([]string{string(b), s[l:]}, "")
}
コード例 #19
0
ファイル: engine.go プロジェクト: machinaut/oh
func Start() {
	proc0 = NewProcess(psNone, nil, nil)

	proc0.Scratch = Cons(NewStatus(0), proc0.Scratch)

	e, s := proc0.Dynamic, proc0.Lexical.Expose()

	e.Add(NewSymbol("$stdin"), channel(proc0, os.Stdin, nil))
	e.Add(NewSymbol("$stdout"), channel(proc0, nil, os.Stdout))
	e.Add(NewSymbol("$stderr"), channel(proc0, nil, os.Stderr))

	if wd, err := os.Getwd(); err == nil {
		e.Add(NewSymbol("$cwd"), NewSymbol(wd))
	}

	s.PrivateState("and", psAnd)
	s.PrivateState("block", psBlock)
	s.PrivateState("backtick", psBacktick)
	s.PrivateState("define", psDefine)
	s.PrivateState("dynamic", psDynamic)
	s.PrivateState("for", psFor)
	s.PrivateState("builtin", psBuiltin)
	s.PrivateState("if", psIf)
	s.PrivateState("import", psImport)
	s.PrivateState("source", psSource)
	s.PrivateState("method", psMethod)
	s.PrivateState("object", psObject)
	s.PrivateState("or", psOr)
	s.PrivateState("quote", psQuote)
	s.PrivateState("set", psSet)
	s.PrivateState("setenv", psSetenv)
	s.PrivateState("spawn", psSpawn)
	s.PrivateState("splice", psSplice)
	s.PrivateState("while", psWhile)

	s.PublicState("public", psPublic)

	s.PrivateState("background", psBackground)
	s.PrivateState("pipe-stdout", psPipeStdout)
	s.PrivateState("pipe-stderr", psPipeStderr)
	s.PrivateState("redirect-stdin", psRedirectStdin)
	s.PrivateState("redirect-stdout", psRedirectStdout)
	s.PrivateState("redirect-stderr", psRedirectStderr)
	s.PrivateState("append-stdout", psAppendStdout)
	s.PrivateState("append-stderr", psAppendStderr)
	s.PrivateState("andf", psAndf)
	s.PrivateState("orf", psOrf)

	/* Builtins. */
	s.PrivateFunction("cd", func(p *Process, args Cell) bool {
		err, status := os.Chdir(Raw(Car(args))), 0
		if err != nil {
			status = int(err.(*os.PathError).Error.(os.Errno))
		}
		SetCar(p.Scratch, NewStatus(int64(status)))

		if wd, err := os.Getwd(); err == nil {
			p.Dynamic.Add(NewSymbol("$cwd"), NewSymbol(wd))
		}

		return false
	})
	s.PrivateFunction("debug", func(p *Process, args Cell) bool {
		debug(p, "debug")

		return false
	})
	s.PrivateFunction("exit", func(p *Process, args Cell) bool {
		var status int64 = 0

		a, ok := Car(args).(Atom)
		if ok {
			status = a.Status()
		}

		p.Scratch = List(NewStatus(status))
		p.Stack = Null

		return true
	})

	s.PublicMethod("child", func(p *Process, args Cell) bool {
		o := Car(p.Scratch).(*Method).Self.Expose()

		SetCar(p.Scratch, NewObject(NewScope(o)))

		return false
	})
	s.PublicMethod("clone", func(p *Process, args Cell) bool {
		o := Car(p.Scratch).(*Method).Self.Expose()

		SetCar(p.Scratch, NewObject(o.Copy()))

		return false
	})

	s.PrivateMethod("apply", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Car(args))
		next(p)

		p.Scratch = Cons(nil, p.Scratch)
		for args = Cdr(args); args != Null; args = Cdr(args) {
			p.Scratch = Cons(Car(args), p.Scratch)
		}

		return true
	})
	s.PrivateMethod("append", func(p *Process, args Cell) bool {
		/*
		 * NOTE: Our append works differently than Scheme's append.
		 *       To mimic Scheme's behavior used append l1 @l2 ... @ln
		 */

		/* TODO: We should just copy this list: ... */
		l := Car(args)

		/* TODO: ... and then set it's cdr to cdr(args). */
		argv := make([]Cell, 0)
		for args = Cdr(args); args != Null; args = Cdr(args) {
			argv = append(argv, Car(args))
		}

		SetCar(p.Scratch, Append(l, argv...))

		return false
	})
	s.PrivateMethod("car", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Caar(args))

		return false
	})
	s.PrivateMethod("cdr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cdar(args))

		return false
	})
	s.PrivateMethod("caar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Caaar(args))

		return false
	})
	s.PrivateMethod("cadr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cadar(args))

		return false
	})
	s.PrivateMethod("cdar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cdaar(args))

		return false
	})
	s.PrivateMethod("cddr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cddar(args))

		return false
	})
	s.PrivateMethod("caaar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Car(Caaar(args)))

		return false
	})
	s.PrivateMethod("caadr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Car(Cadar(args)))

		return false
	})
	s.PrivateMethod("cadar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Car(Cdaar(args)))

		return false
	})
	s.PrivateMethod("caddr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Car(Cddar(args)))

		return false
	})
	s.PrivateMethod("cdaar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cdr(Caaar(args)))

		return false
	})
	s.PrivateMethod("cdadr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cdr(Cadar(args)))

		return false
	})
	s.PrivateMethod("cddar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cdr(Cdaar(args)))

		return false
	})
	s.PrivateMethod("cdddr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cdr(Cddar(args)))

		return false
	})
	s.PrivateMethod("caaaar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Caar(Caaar(args)))

		return false
	})
	s.PrivateMethod("caaadr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Caar(Cadar(args)))

		return false
	})
	s.PrivateMethod("caadar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Caar(Cdaar(args)))

		return false
	})
	s.PrivateMethod("caaddr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Caar(Cddar(args)))

		return false
	})
	s.PrivateMethod("cadaar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cadr(Caaar(args)))

		return false
	})
	s.PrivateMethod("cadadr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cadr(Cadar(args)))

		return false
	})
	s.PrivateMethod("caddar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cadr(Cdaar(args)))

		return false
	})
	s.PrivateMethod("cadddr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cadr(Cddar(args)))

		return false
	})
	s.PrivateMethod("cdaaar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cdar(Caaar(args)))

		return false
	})
	s.PrivateMethod("cdaadr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cdar(Cadar(args)))

		return false
	})
	s.PrivateMethod("cdadar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cdar(Cdaar(args)))

		return false
	})
	s.PrivateMethod("cdaddr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cdar(Cddar(args)))

		return false
	})
	s.PrivateMethod("cddaar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cddr(Caaar(args)))

		return false
	})
	s.PrivateMethod("cddadr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cddr(Cadar(args)))

		return false
	})
	s.PrivateMethod("cdddar", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cddr(Cdaar(args)))

		return false
	})
	s.PrivateMethod("cddddr", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cddr(Cddar(args)))

		return false
	})
	s.PrivateMethod("cons", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Cons(Car(args), Cadr(args)))

		return false
	})
	s.PrivateMethod("eval", func(p *Process, args Cell) bool {
		p.ReplaceState(psEvalCommand)

		p.Code = Car(args)
		p.Scratch = Cdr(p.Scratch)

		return true
	})
	s.PrivateMethod("length", func(p *Process, args Cell) bool {
		var l int64 = 0

		switch c := Car(args); c.(type) {
		case *String, *Symbol:
			l = int64(len(Raw(c)))
		default:
			l = Length(c)
		}

		SetCar(p.Scratch, NewInteger(l))

		return false
	})
	s.PrivateMethod("is-control", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsControl(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("is-digit", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsDigit(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("is-graphic", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsGraphic(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("is-letter", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsLetter(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("is-lower", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsLower(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("is-mark", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsMark(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("is-print", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsPrint(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("is-punct", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsPunct(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("is-space", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsSpace(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("is-symbol", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsSymbol(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("is-title", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsTitle(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("is-upper", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsUpper(int(t.Int())))
		default:
			r = Null
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("list", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, args)

		return false
	})
	s.PrivateMethod("list-to-string", func(p *Process, args Cell) bool {
		s := ""
		for l := Car(args); l != Null; l = Cdr(l) {
			s = fmt.Sprintf("%s%c", s, int(Car(l).(Atom).Int()))
		}

		SetCar(p.Scratch, NewString(s))

		return false
	})
	s.PrivateMethod("list-to-symbol", func(p *Process, args Cell) bool {
		s := ""
		for l := Car(args); l != Null; l = Cdr(l) {
			s = fmt.Sprintf("%s%c", s, int(Car(l).(Atom).Int()))
		}

		SetCar(p.Scratch, NewSymbol(s))

		return false
	})
	s.PrivateMethod("open", func(p *Process, args Cell) bool {
		name := Raw(Car(args))
		mode := Raw(Cadr(args))

		flags := os.O_CREATE

		if strings.IndexAny(mode, "r") != -1 {
			flags |= os.O_WRONLY
		} else if strings.IndexAny(mode, "aw") != -1 {
			flags |= os.O_RDONLY
		} else {
			flags |= os.O_RDWR
		}

		if strings.IndexAny(mode, "a") != -1 {
			flags |= os.O_APPEND
		}

		f, err := os.OpenFile(name, flags, 0666)
		if err != nil {
			panic(err)
		}

		SetCar(p.Scratch, channel(p, f, f))

		return false
	})
	s.PrivateMethod("reverse", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Reverse(Car(args)))

		return false
	})
	s.PrivateMethod("set-car", func(p *Process, args Cell) bool {
		SetCar(Car(args), Cadr(args))
		SetCar(p.Scratch, Cadr(args))

		return false
	})
	s.PrivateMethod("set-cdr", func(p *Process, args Cell) bool {
		SetCdr(Car(args), Cadr(args))
		SetCar(p.Scratch, Cadr(args))

		return false
	})
	s.PrivateMethod("sprintf", func(p *Process, args Cell) bool {
		f := Raw(Car(args))

		argv := []interface{}{}
		for l := Cdr(args); l != Null; l = Cdr(l) {
			switch t := Car(l).(type) {
			case *Boolean:
				argv = append(argv, *t)
			case *Integer:
				argv = append(argv, *t)
			case *Status:
				argv = append(argv, *t)
			case *Float:
				argv = append(argv, *t)
			default:
				argv = append(argv, Raw(t))
			}
		}

		s := fmt.Sprintf(f, argv...)
		SetCar(p.Scratch, NewString(s))

		return false
	})
	s.PrivateMethod("substring", func(p *Process, args Cell) bool {
		var r Cell

		s := []int(Raw(Car(args)))

		start := int(Cadr(args).(Atom).Int())
		end := len(s)

		if Cddr(args) != Null {
			end = int(Caddr(args).(Atom).Int())
		}

		switch t := Car(args).(type) {
		case *String:
			r = NewString(string(s[start:end]))
		case *Symbol:
			r = NewSymbol(string(s[start:end]))
		default:
			r = Null
		}
		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("text-to-list", func(p *Process, args Cell) bool {
		l := Null
		for _, char := range Raw(Car(args)) {
			l = Cons(NewInteger(int64(char)), l)
		}

		SetCar(p.Scratch, Reverse(l))

		return false
	})
	s.PrivateMethod("to-lower", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewInteger(int64(unicode.ToLower(int(t.Int()))))
		case *String:
			r = NewString(strings.ToLower(Raw(t)))
		case *Symbol:
			r = NewSymbol(strings.ToLower(Raw(t)))
		default:
			r = NewInteger(0)
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("to-title", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewInteger(int64(unicode.ToTitle(int(t.Int()))))
		case *String:
			r = NewString(strings.ToTitle(Raw(t)))
		case *Symbol:
			r = NewSymbol(strings.ToTitle(Raw(t)))
		default:
			r = NewInteger(0)
		}

		SetCar(p.Scratch, r)

		return false
	})
	s.PrivateMethod("to-upper", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewInteger(int64(unicode.ToUpper(int(t.Int()))))
		case *String:
			r = NewString(strings.ToUpper(Raw(t)))
		case *Symbol:
			r = NewSymbol(strings.ToUpper(Raw(t)))
		default:
			r = NewInteger(0)
		}

		SetCar(p.Scratch, r)

		return false
	})

	/* Predicates. */
	s.PrivateMethod("is-atom", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, NewBoolean(IsAtom(Car(args))))

		return false
	})
	s.PrivateMethod("is-boolean",
		func(p *Process, args Cell) bool {
			_, ok := Car(args).(*Boolean)
			SetCar(p.Scratch, NewBoolean(ok))

			return false
		})
	s.PrivateMethod("is-channel",
		func(p *Process, args Cell) bool {
			o, ok := Car(args).(Interface)
			if ok {
				ok = false
				c := Resolve(o.Expose(), nil, NewSymbol("guts"))
				if c != nil {
					_, ok = c.GetValue().(*Channel)
				}
			}

			SetCar(p.Scratch, NewBoolean(ok))

			return false
		})
	s.PrivateMethod("is-cons", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, NewBoolean(IsCons(Car(args))))

		return false
	})
	s.PrivateMethod("is-float", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Float)
		SetCar(p.Scratch, NewBoolean(ok))

		return false
	})
	s.PrivateMethod("is-integer",
		func(p *Process, args Cell) bool {
			_, ok := Car(args).(*Integer)
			SetCar(p.Scratch, NewBoolean(ok))

			return false
		})
	s.PrivateMethod("is-list", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, NewBoolean(IsList(Car(args))))

		return false
	})
	s.PrivateMethod("is-method", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Method)
		SetCar(p.Scratch, NewBoolean(ok))

		return false
	})
	s.PrivateMethod("is-null", func(p *Process, args Cell) bool {
		ok := Car(args) == Null
		SetCar(p.Scratch, NewBoolean(ok))

		return false
	})
	s.PrivateMethod("is-number", func(p *Process, args Cell) bool {
		_, ok := Car(args).(Number)
		SetCar(p.Scratch, NewBoolean(ok))

		return false
	})
	s.PrivateMethod("is-object", func(p *Process, args Cell) bool {
		_, ok := Car(args).(Interface)
		SetCar(p.Scratch, NewBoolean(ok))

		return false
	})
	s.PrivateMethod("is-status", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Status)
		SetCar(p.Scratch, NewBoolean(ok))

		return false
	})
	s.PrivateMethod("is-string", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*String)
		SetCar(p.Scratch, NewBoolean(ok))

		return false
	})
	s.PrivateMethod("is-symbol", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Symbol)
		SetCar(p.Scratch, NewBoolean(ok))

		return false
	})
	s.PrivateMethod("is-text", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Symbol)
		if !ok {
			_, ok = Car(args).(*String)
		}
		SetCar(p.Scratch, NewBoolean(ok))

		return false
	})

	/* Generators. */
	s.PrivateMethod("boolean", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, NewBoolean(Car(args).Bool()))

		return false
	})
	s.PrivateMethod("channel", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, channel(p, nil, nil))

		return false
	})
	s.PrivateMethod("float", func(p *Process, args Cell) bool {
		SetCar(p.Scratch,
			NewFloat(Car(args).(Atom).Float()))

		return false
	})
	s.PrivateMethod("integer", func(p *Process, args Cell) bool {
		SetCar(p.Scratch,
			NewInteger(Car(args).(Atom).Int()))

		return false
	})
	s.PrivateMethod("status", func(p *Process, args Cell) bool {
		SetCar(p.Scratch,
			NewStatus(Car(args).(Atom).Status()))

		return false
	})
	s.PrivateMethod("string", func(p *Process, args Cell) bool {
		SetCar(p.Scratch,
			NewString(Car(args).String()))

		return false
	})
	s.PrivateMethod("symbol", func(p *Process, args Cell) bool {
		SetCar(p.Scratch,
			NewSymbol(Raw(Car(args))))

		return false
	})

	/* Relational. */
	s.PrivateMethod("eq", func(p *Process, args Cell) bool {
		prev := Car(args)

		SetCar(p.Scratch, False)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args)

			if !prev.Equal(curr) {
				return false
			}

			prev = curr
		}

		SetCar(p.Scratch, True)
		return false
	})
	s.PrivateMethod("ge", func(p *Process, args Cell) bool {
		prev := Car(args).(Atom)

		SetCar(p.Scratch, False)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args).(Atom)

			if prev.Less(curr) {
				return false
			}

			prev = curr
		}

		SetCar(p.Scratch, True)
		return false
	})
	s.PrivateMethod("gt", func(p *Process, args Cell) bool {
		prev := Car(args).(Atom)

		SetCar(p.Scratch, False)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args).(Atom)

			if !prev.Greater(curr) {
				return false
			}

			prev = curr
		}

		SetCar(p.Scratch, True)
		return false
	})
	s.PrivateMethod("is", func(p *Process, args Cell) bool {
		prev := Car(args)

		SetCar(p.Scratch, False)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args)

			if prev != curr {
				return false
			}

			prev = curr
		}

		SetCar(p.Scratch, True)
		return false
	})
	s.PrivateMethod("le", func(p *Process, args Cell) bool {
		prev := Car(args).(Atom)

		SetCar(p.Scratch, False)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args).(Atom)

			if prev.Greater(curr) {
				return false
			}

			prev = curr
		}

		SetCar(p.Scratch, True)
		return false
	})
	s.PrivateMethod("lt", func(p *Process, args Cell) bool {
		prev := Car(args).(Atom)

		SetCar(p.Scratch, False)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args).(Atom)

			if !prev.Less(curr) {
				return false
			}

			prev = curr
		}

		SetCar(p.Scratch, True)
		return false
	})
	s.PrivateMethod("match", func(p *Process, args Cell) bool {
		pattern := Raw(Car(args))
		text := Raw(Cadr(args))

		ok, err := path.Match(pattern, text)
		if err != nil {
			panic(err)
		}

		SetCar(p.Scratch, NewBoolean(ok))

		return false
	})
	s.PrivateMethod("ne", func(p *Process, args Cell) bool {
		/*
		 * This should really check to make sure no arguments are equal.
		 * Currently it only checks whether adjacent pairs are not equal.
		 */

		prev := Car(args)

		SetCar(p.Scratch, False)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args)

			if prev.Equal(curr) {
				return false
			}

			prev = curr
		}

		SetCar(p.Scratch, True)
		return false
	})
	s.PrivateMethod("not", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, NewBoolean(!Car(args).Bool()))

		return false
	})

	/* Arithmetic. */
	s.PrivateMethod("add", func(p *Process, args Cell) bool {
		acc := Car(args).(Atom)

		for Cdr(args) != Null {
			args = Cdr(args)
			acc = acc.Add(Car(args))

		}

		SetCar(p.Scratch, acc)
		return false
	})
	s.PrivateMethod("sub", func(p *Process, args Cell) bool {
		acc := Car(args).(Number)

		for Cdr(args) != Null {
			args = Cdr(args)
			acc = acc.Subtract(Car(args))
		}

		SetCar(p.Scratch, acc)
		return false
	})
	s.PrivateMethod("div", func(p *Process, args Cell) bool {
		acc := Car(args).(Number)

		for Cdr(args) != Null {
			args = Cdr(args)
			acc = acc.Divide(Car(args))
		}

		SetCar(p.Scratch, acc)
		return false
	})
	s.PrivateMethod("mod", func(p *Process, args Cell) bool {
		acc := Car(args).(Number)

		for Cdr(args) != Null {
			args = Cdr(args)
			acc = acc.Modulo(Car(args))
		}

		SetCar(p.Scratch, acc)
		return false
	})
	s.PrivateMethod("mul", func(p *Process, args Cell) bool {
		acc := Car(args).(Atom)

		for Cdr(args) != Null {
			args = Cdr(args)
			acc = acc.Multiply(Car(args))
		}

		SetCar(p.Scratch, acc)
		return false
	})

	e.Add(NewSymbol("$$"), NewInteger(int64(os.Getpid())))

	/* Command-line arguments */
	args := Null
	if len(os.Args) > 1 {
		e.Add(NewSymbol("$0"), NewSymbol(os.Args[1]))

		for i, v := range os.Args[2:] {
			e.Add(NewSymbol("$"+strconv.Itoa(i+1)), NewSymbol(v))
		}

		for i := len(os.Args) - 1; i > 1; i-- {
			args = Cons(NewSymbol(os.Args[i]), args)
		}
	} else {
		e.Add(NewSymbol("$0"), NewSymbol(os.Args[0]))
	}
	e.Add(NewSymbol("$args"), args)

	/* Environment variables. */
	for _, s := range os.Environ() {
		kv := strings.SplitN(s, "=", 2)
		e.Add(NewSymbol("$"+kv[0]), NewSymbol(kv[1]))
	}

	Parse(bufio.NewReader(strings.NewReader(`
define echo: builtin: $stdout::write @$args
define expand: builtin: return $args
define printf: method: echo: sprintf (car $args) @(cdr $args)
define read: builtin: $stdin::read
define readline: builtin: $stdin::readline
define write: method: $stdout::write @$args
define list-tail: method k x {
    if k {
        list-tail (sub k 1): cdr x
    } else {
        return x
    }
}
define list-ref: method k x: car: list-tail k x
`)), Evaluate)

	/* Read and execute rc script if it exists. */
	rc := filepath.Join(os.Getenv("HOME"), ".ohrc")
	if _, err := os.Stat(rc); err == nil {
		proc0.NewState(psEvalCommand)
		proc0.Code = List(NewSymbol("source"), NewSymbol(rc))

		run(proc0)

		proc0.Scratch = Cdr(proc0.Scratch)
	}
}
コード例 #20
0
ファイル: engine.go プロジェクト: Travel-Agent/oh
func Start(i bool) {
	interactive = i

	irq = make(chan os.Signal, 1)
	signal.Notify(irq, syscall.SIGINT)

	proc0 = NewProcess(psEvalTopBlock, nil, nil)

	block0 = Cons(nil, Null)
	proc0.Code = block0

	proc0.Scratch = Cons(NewStatus(0), proc0.Scratch)

	e, s := proc0.Dynamic, proc0.Lexical.Expose()

	e.Define(NewSymbol("False"), False)
	e.Define(NewSymbol("True"), True)

	e.Define(NewSymbol("$stdin"), channel(proc0, os.Stdin, nil, -1))
	e.Define(NewSymbol("$stdout"), channel(proc0, nil, os.Stdout, -1))
	e.Define(NewSymbol("$stderr"), channel(proc0, nil, os.Stderr, -1))

	if wd, err := os.Getwd(); err == nil {
		e.Define(NewSymbol("$cwd"), NewSymbol(wd))
	}

	s.DefineState("block", psBlock)
	s.DefineState("builtin", psBuiltin)
	s.DefineState("define", psDefine)
	s.DefineState("dynamic", psDynamic)
	s.DefineState("if", psIf)
	s.DefineState("method", psMethod)
	s.DefineState("set", psSet)
	s.DefineState("setenv", psSetenv)
	s.DefineState("spawn", psSpawn)
	s.DefineState("splice", psSplice)
	s.DefineState("syntax", psSyntax)
	s.DefineState("while", psWhile)

	s.PublicState("public", psPublic)

	/* Builtins. */
	s.DefineFunction("cd", func(p *Process, args Cell) bool {
		err := os.Chdir(Raw(Car(args)))
		status := 0
		if err != nil {
			status = 1
		}

		if wd, err := os.Getwd(); err == nil {
			p.Dynamic.Define(NewSymbol("$cwd"), NewSymbol(wd))
		}

		return p.Return(NewStatus(int64(status)))
	})
	s.DefineFunction("debug", func(p *Process, args Cell) bool {
		debug(p, "debug")

		return false
	})
	s.DefineFunction("exit", func(p *Process, args Cell) bool {
		var status int64 = 0

		a, ok := Car(args).(Atom)
		if ok {
			status = a.Status()
		}

		p.Scratch = List(NewStatus(status))
		p.Stack = Null

		return true
	})
	s.DefineFunction("module", func(p *Process, args Cell) bool {
		str, err := module(Raw(Car(args)))

		if err != nil {
			return p.Return(Null)
		}

		sym := NewSymbol(str)
		c := Resolve(p.Lexical, p.Dynamic, sym)

		if c == nil {
			return p.Return(sym)
		}

		return p.Return(c.GetValue())
	})

	s.PublicMethod("child", func(p *Process, args Cell) bool {
		o := Car(p.Scratch).(*Applicative).Self.Expose()

		return p.Return(NewObject(NewLexicalScope(o)))
	})
	s.PublicMethod("clone", func(p *Process, args Cell) bool {
		o := Car(p.Scratch).(*Applicative).Self.Expose()

		return p.Return(NewObject(o.Copy()))
	})
	s.PublicMethod("exists", func(p *Process, args Cell) bool {
		l := Car(p.Scratch).(*Applicative).Self
		c := Resolve(l, p.Dynamic, NewSymbol(Raw(Car(args))))

		return p.Return(NewBoolean(c != nil))
	})
	s.PublicMethod("unset", func(p *Process, args Cell) bool {
		l := Car(p.Scratch).(*Applicative).Self
		r := l.Remove(NewSymbol(Raw(Car(args))))

		return p.Return(NewBoolean(r))
	})

	s.DefineMethod("append", func(p *Process, args Cell) bool {
		/*
		 * NOTE: Our append works differently than Scheme's append.
		 *       To mimic Scheme's behavior used append l1 @l2 ... @ln
		 */

		/* TODO: We should just copy this list: ... */
		l := Car(args)

		/* TODO: ... and then set it's cdr to cdr(args). */
		argv := make([]Cell, 0)
		for args = Cdr(args); args != Null; args = Cdr(args) {
			argv = append(argv, Car(args))
		}

		return p.Return(Append(l, argv...))
	})
	s.DefineMethod("apply", func(p *Process, args Cell) bool {
		SetCar(p.Scratch, Car(args))
		head(p)

		p.Scratch = Cons(nil, p.Scratch)
		for args = Cdr(args); args != Null; args = Cdr(args) {
			p.Scratch = Cons(Car(args), p.Scratch)
		}

		return true
	})
	s.DefineMethod("car", func(p *Process, args Cell) bool {
		return p.Return(Caar(args))
	})
	s.DefineMethod("cdr", func(p *Process, args Cell) bool {
		return p.Return(Cdar(args))
	})
	s.DefineMethod("cons", func(p *Process, args Cell) bool {
		return p.Return(Cons(Car(args), Cadr(args)))
	})
	s.PublicMethod("eval", func(p *Process, args Cell) bool {
		scope := Car(p.Scratch).(*Applicative).Self.Expose()
		p.RemoveState()
		if p.Lexical != scope {
			p.NewState(SaveLexical)
			p.Lexical = scope
		}
		p.NewState(psEvalElement)
		p.Code = Car(args)
		p.Scratch = Cdr(p.Scratch)

		return true
	})
	s.DefineMethod("length", func(p *Process, args Cell) bool {
		var l int64 = 0

		switch c := Car(args); c.(type) {
		case *String, *Symbol:
			l = int64(len(Raw(c)))
		default:
			l = Length(c)
		}

		return p.Return(NewInteger(l))
	})
	s.DefineMethod("list", func(p *Process, args Cell) bool {
		return p.Return(args)
	})
	s.DefineMethod("open", func(p *Process, args Cell) bool {
		name := Raw(Car(args))
		mode := Raw(Cadr(args))
		flags := 0

		if strings.IndexAny(mode, "-") == -1 {
			flags = os.O_CREATE
		}

		read := false
		if strings.IndexAny(mode, "r") != -1 {
			read = true
		}

		write := false
		if strings.IndexAny(mode, "w") != -1 {
			write = true
			if strings.IndexAny(mode, "a") == -1 {
				flags |= os.O_TRUNC
			}
		}

		if strings.IndexAny(mode, "a") != -1 {
			write = true
			flags |= os.O_APPEND
		}

		if read == write {
			read = true
			write = true
			flags |= os.O_RDWR
		} else if write {
			flags |= os.O_WRONLY
		}

		f, err := os.OpenFile(name, flags, 0666)
		if err != nil {
			panic(err)
		}

		r := f
		if !read {
			r = nil
		}

		w := f
		if !write {
			w = nil
		}

		return p.Return(channel(p, r, w, -1))
	})
	s.DefineMethod("reverse", func(p *Process, args Cell) bool {
		return p.Return(Reverse(Car(args)))
	})
	s.DefineMethod("set-car", func(p *Process, args Cell) bool {
		SetCar(Car(args), Cadr(args))

		return p.Return(Cadr(args))
	})
	s.DefineMethod("set-cdr", func(p *Process, args Cell) bool {
		SetCdr(Car(args), Cadr(args))

		return p.Return(Cadr(args))
	})

	/* Predicates. */
	s.DefineMethod("is-atom", func(p *Process, args Cell) bool {
		return p.Return(NewBoolean(IsAtom(Car(args))))
	})
	s.DefineMethod("is-boolean", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Boolean)

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-channel", func(p *Process, args Cell) bool {
		o, ok := Car(args).(Context)
		if !ok {
			return p.Return(False)
		}

		g := Resolve(o.Expose(), nil, NewSymbol("guts"))
		if g == nil {
			return p.Return(False)
		}

		c, ok := g.GetValue().(*Channel)
		if !ok {
			return p.Return(False)
		}

		ok = (c.ReadFd() == nil && c.WriteFd() == nil)

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-cons", func(p *Process, args Cell) bool {
		return p.Return(NewBoolean(IsCons(Car(args))))
	})
	s.DefineMethod("is-float", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Float)

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-integer", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Integer)

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-list", func(p *Process, args Cell) bool {
		return p.Return(NewBoolean(IsList(Car(args))))
	})
	s.DefineMethod("is-method", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Applicative)

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-null", func(p *Process, args Cell) bool {
		ok := Car(args) == Null

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-number", func(p *Process, args Cell) bool {
		_, ok := Car(args).(Number)

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-object", func(p *Process, args Cell) bool {
		_, ok := Car(args).(Context)

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-pipe", func(p *Process, args Cell) bool {
		o, ok := Car(args).(Context)
		if !ok {
			return p.Return(False)
		}

		g := Resolve(o.Expose(), nil, NewSymbol("guts"))
		if g == nil {
			return p.Return(False)
		}

		c, ok := g.GetValue().(*Channel)
		if !ok {
			return p.Return(False)
		}

		ok = (c.ReadFd() != nil || c.WriteFd() != nil)

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-status", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Status)

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-string", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*String)

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-symbol", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Symbol)

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("is-syntax", func(p *Process, args Cell) bool {
		_, ok := Car(args).(*Operative)

		return p.Return(NewBoolean(ok))
	})

	/* Generators. */
	s.DefineMethod("boolean", func(p *Process, args Cell) bool {
		return p.Return(NewBoolean(Car(args).Bool()))
	})
	s.DefineMethod("channel", func(p *Process, args Cell) bool {
		c := 0
		if args != Null {
			c = int(Car(args).(Atom).Int())
		}

		return p.Return(channel(p, nil, nil, c))
	})
	s.DefineMethod("float", func(p *Process, args Cell) bool {
		return p.Return(NewFloat(Car(args).(Atom).Float()))
	})
	s.DefineMethod("integer", func(p *Process, args Cell) bool {
		return p.Return(NewInteger(Car(args).(Atom).Int()))
	})
	s.DefineMethod("pipe", func(p *Process, args Cell) bool {
		return p.Return(channel(p, nil, nil, -1))
	})
	s.DefineMethod("status", func(p *Process, args Cell) bool {
		return p.Return(NewStatus(Car(args).(Atom).Status()))
	})
	s.DefineMethod("string", func(p *Process, args Cell) bool {
		return p.Return(NewString(Car(args).String()))
	})
	s.DefineMethod("symbol", func(p *Process, args Cell) bool {
		return p.Return(NewSymbol(Raw(Car(args))))
	})

	/* Relational. */
	s.DefineMethod("eq", func(p *Process, args Cell) bool {
		prev := Car(args)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args)

			if !prev.Equal(curr) {
				return p.Return(False)
			}

			prev = curr
		}

		return p.Return(True)
	})
	s.DefineMethod("ge", func(p *Process, args Cell) bool {
		prev := Car(args).(Atom)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args).(Atom)

			if prev.Less(curr) {
				return p.Return(False)
			}

			prev = curr
		}

		return p.Return(True)
	})
	s.DefineMethod("gt", func(p *Process, args Cell) bool {
		prev := Car(args).(Atom)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args).(Atom)

			if !prev.Greater(curr) {
				return p.Return(False)
			}

			prev = curr
		}

		return p.Return(True)
	})
	s.DefineMethod("is", func(p *Process, args Cell) bool {
		prev := Car(args)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args)

			if prev != curr {
				return p.Return(False)
			}

			prev = curr
		}

		return p.Return(True)
	})
	s.DefineMethod("le", func(p *Process, args Cell) bool {
		prev := Car(args).(Atom)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args).(Atom)

			if prev.Greater(curr) {
				return p.Return(False)
			}

			prev = curr
		}

		return p.Return(True)
	})
	s.DefineMethod("lt", func(p *Process, args Cell) bool {
		prev := Car(args).(Atom)

		for Cdr(args) != Null {
			args = Cdr(args)
			curr := Car(args).(Atom)

			if !prev.Less(curr) {
				return p.Return(False)
			}

			prev = curr
		}

		return p.Return(True)
	})
	s.DefineMethod("match", func(p *Process, args Cell) bool {
		pattern := Raw(Car(args))
		text := Raw(Cadr(args))

		ok, err := path.Match(pattern, text)
		if err != nil {
			panic(err)
		}

		return p.Return(NewBoolean(ok))
	})
	s.DefineMethod("ne", func(p *Process, args Cell) bool {
		for l1 := args; l1 != Null; l1 = Cdr(l1) {
			for l2 := Cdr(l1); l2 != Null; l2 = Cdr(l2) {
				v1 := Car(l1)
				v2 := Car(l2)

				if v1.Equal(v2) {
					return p.Return(False)
				}
			}
		}

		return p.Return(True)
	})
	s.DefineMethod("not", func(p *Process, args Cell) bool {
		return p.Return(NewBoolean(!Car(args).Bool()))
	})

	/* Arithmetic. */
	s.DefineMethod("add", func(p *Process, args Cell) bool {
		acc := Car(args).(Atom)

		for Cdr(args) != Null {
			args = Cdr(args)
			acc = acc.Add(Car(args))

		}

		return p.Return(acc)
	})
	s.DefineMethod("sub", func(p *Process, args Cell) bool {
		acc := Car(args).(Number)

		for Cdr(args) != Null {
			args = Cdr(args)
			acc = acc.Subtract(Car(args))
		}

		return p.Return(acc)
	})
	s.DefineMethod("div", func(p *Process, args Cell) bool {
		acc := Car(args).(Number)

		for Cdr(args) != Null {
			args = Cdr(args)
			acc = acc.Divide(Car(args))
		}

		return p.Return(acc)
	})
	s.DefineMethod("mod", func(p *Process, args Cell) bool {
		acc := Car(args).(Number)

		for Cdr(args) != Null {
			args = Cdr(args)
			acc = acc.Modulo(Car(args))
		}

		return p.Return(acc)
	})
	s.DefineMethod("mul", func(p *Process, args Cell) bool {
		acc := Car(args).(Atom)

		for Cdr(args) != Null {
			args = Cdr(args)
			acc = acc.Multiply(Car(args))
		}

		return p.Return(acc)
	})

	/* Standard namespaces. */
	list := NewObject(NewLexicalScope(s))
	s.Define(NewSymbol("List"), list)

	list.PublicMethod("to-string", func(p *Process, args Cell) bool {
		s := ""
		for l := Car(args); l != Null; l = Cdr(l) {
			s = fmt.Sprintf("%s%c", s, int(Car(l).(Atom).Int()))
		}

		return p.Return(NewString(s))
	})
	list.PublicMethod("to-symbol", func(p *Process, args Cell) bool {
		s := ""
		for l := Car(args); l != Null; l = Cdr(l) {
			s = fmt.Sprintf("%s%c", s, int(Car(l).(Atom).Int()))
		}

		return p.Return(NewSymbol(s))
	})

	text := NewObject(NewLexicalScope(s))
	s.Define(NewSymbol("Text"), text)

	text.PublicMethod("is-control", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsControl(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("is-digit", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsDigit(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("is-graphic", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsGraphic(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("is-letter", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsLetter(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("is-lower", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsLower(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("is-mark", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsMark(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("is-print", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsPrint(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("is-punct", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsPunct(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("is-space", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsSpace(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("is-symbol", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsSymbol(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("is-title", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsTitle(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("is-upper", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewBoolean(unicode.IsUpper(rune(t.Int())))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("join", func(p *Process, args Cell) bool {
		str := false
		sep := Car(args)
		list := Cdr(args)

		arr := make([]string, Length(list))

		for i := 0; list != Null; i++ {
			_, str = Car(list).(*String)
			arr[i] = string(Raw(Car(list)))
			list = Cdr(list)
		}

		r := strings.Join(arr, string(Raw(sep)))

		if str {
			return p.Return(NewString(r))
		}
		return p.Return(NewSymbol(r))
	})
	text.PublicMethod("split", func(p *Process, args Cell) bool {
		var r Cell = Null

		sep := Car(args)
		str := Cadr(args)

		l := strings.Split(string(Raw(str)), string(Raw(sep)))

		for i := len(l) - 1; i >= 0; i-- {
			switch str.(type) {
			case *Symbol:
				r = Cons(NewSymbol(l[i]), r)
			case *String:
				r = Cons(NewString(l[i]), r)
			}
		}

		return p.Return(r)
	})
	text.PublicMethod("sprintf", func(p *Process, args Cell) bool {
		f := Raw(Car(args))

		argv := []interface{}{}
		for l := Cdr(args); l != Null; l = Cdr(l) {
			switch t := Car(l).(type) {
			case *Boolean:
				argv = append(argv, *t)
			case *Integer:
				argv = append(argv, *t)
			case *Status:
				argv = append(argv, *t)
			case *Float:
				argv = append(argv, *t)
			default:
				argv = append(argv, Raw(t))
			}
		}

		s := fmt.Sprintf(f, argv...)

		return p.Return(NewString(s))
	})
	text.PublicMethod("substring", func(p *Process, args Cell) bool {
		var r Cell

		s := []rune(Raw(Car(args)))

		start := int(Cadr(args).(Atom).Int())
		end := len(s)

		if Cddr(args) != Null {
			end = int(Caddr(args).(Atom).Int())
		}

		switch Car(args).(type) {
		case *String:
			r = NewString(string(s[start:end]))
		case *Symbol:
			r = NewSymbol(string(s[start:end]))
		default:
			r = Null
		}

		return p.Return(r)
	})
	text.PublicMethod("to-list", func(p *Process, args Cell) bool {
		l := Null
		for _, char := range Raw(Car(args)) {
			l = Cons(NewInteger(int64(char)), l)
		}

		return p.Return(Reverse(l))
	})
	text.PublicMethod("lower", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewInteger(int64(unicode.ToLower(rune(t.Int()))))
		case *String:
			r = NewString(strings.ToLower(Raw(t)))
		case *Symbol:
			r = NewSymbol(strings.ToLower(Raw(t)))
		default:
			r = NewInteger(0)
		}

		return p.Return(r)
	})
	text.PublicMethod("title", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewInteger(int64(unicode.ToTitle(rune(t.Int()))))
		case *String:
			r = NewString(strings.ToTitle(Raw(t)))
		case *Symbol:
			r = NewSymbol(strings.ToTitle(Raw(t)))
		default:
			r = NewInteger(0)
		}

		return p.Return(r)
	})
	text.PublicMethod("upper", func(p *Process, args Cell) bool {
		var r Cell

		switch t := Car(args).(type) {
		case *Integer:
			r = NewInteger(int64(unicode.ToUpper(rune(t.Int()))))
		case *String:
			r = NewString(strings.ToUpper(Raw(t)))
		case *Symbol:
			r = NewSymbol(strings.ToUpper(Raw(t)))
		default:
			r = NewInteger(0)
		}

		return p.Return(r)
	})

	s.Public(NewSymbol("Root"), s)

	e.Define(NewSymbol("$$"), NewInteger(int64(os.Getpid())))

	/* Command-line arguments */
	args := Null
	if len(os.Args) > 1 {
		e.Define(NewSymbol("$0"), NewSymbol(os.Args[1]))

		for i, v := range os.Args[2:] {
			e.Define(NewSymbol("$"+strconv.Itoa(i+1)), NewSymbol(v))
		}

		for i := len(os.Args) - 1; i > 1; i-- {
			args = Cons(NewSymbol(os.Args[i]), args)
		}
	} else {
		e.Define(NewSymbol("$0"), NewSymbol(os.Args[0]))
	}
	e.Define(NewSymbol("$args"), args)

	/* Environment variables. */
	for _, s := range os.Environ() {
		kv := strings.SplitN(s, "=", 2)
		e.Define(NewSymbol("$"+kv[0]), NewSymbol(kv[1]))
	}

	Parse(bufio.NewReader(strings.NewReader(`
define caar: method (l) as: car: car l
define cadr: method (l) as: car: cdr l
define cdar: method (l) as: cdr: car l
define cddr: method (l) as: cdr: cdr l
define caaar: method (l) as: car: caar l
define caadr: method (l) as: car: cadr l
define cadar: method (l) as: car: cdar l
define caddr: method (l) as: car: cddr l
define cdaar: method (l) as: cdr: caar l
define cdadr: method (l) as: cdr: cadr l
define cddar: method (l) as: cdr: cdar l
define cdddr: method (l) as: cdr: cddr l
define caaaar: method (l) as: caar: caar l
define caaadr: method (l) as: caar: cadr l
define caadar: method (l) as: caar: cdar l
define caaddr: method (l) as: caar: cddr l
define cadaar: method (l) as: cadr: caar l
define cadadr: method (l) as: cadr: cadr l
define caddar: method (l) as: cadr: cdar l
define cadddr: method (l) as: cadr: cddr l
define cdaaar: method (l) as: cdar: caar l
define cdaadr: method (l) as: cdar: cadr l
define cdadar: method (l) as: cdar: cdar l
define cdaddr: method (l) as: cdar: cddr l
define cddaar: method (l) as: cddr: caar l
define cddadr: method (l) as: cddr: cadr l
define cdddar: method (l) as: cddr: cdar l
define cddddr: method (l) as: cddr: cddr l
define $connect: syntax (type out close) as {
    set type: eval type
    set close: eval close
    syntax e (left right) as {
        define p: type
        spawn {
            eval: list 'dynamic out 'p
            e::eval left
            if close: p::writer-close
        }

        dynamic $stdin p
        e::eval right
        if close: p::reader-close
    }
}
define $redirect: syntax (chan mode mthd) as {
    syntax e (c cmd) as {
        define c: e::eval c
        define f '()
        if (not: or (is-channel c) (is-pipe c)) {
            set f: open c mode
            set c f
        }
        eval: list 'dynamic chan 'c
        e::eval cmd
        if (not: is-null f): eval: cons 'f mthd
    }
}
define and: syntax e (: lst) as {
    define r False
    while (not: is-null: car lst) {
        set r: e::eval: car lst
        if (not r): return r
        set lst: cdr lst
    }
    return r
}
define append-stderr: $redirect $stderr "a" writer-close
define append-stdout: $redirect $stdout "a" writer-close
define backtick: syntax e (cmd) as {
    define p: pipe
    define r '()
    spawn {
        dynamic $stdout p
        e::eval cmd
        p::writer-close
    }
    define l: p::readline
    while l {
        set r: append r l
        set l: p::readline
    }
    p::reader-close
    return r
}
define channel-stderr: $connect channel $stderr True
define channel-stdout: $connect channel $stdout True
define echo: builtin (: args) as: $stdout::write @args
define for: method (l m) as {
    define r: cons '() '()
    define c r
    while (not: is-null l) {
        set-cdr c: cons (m: car l) '()
        set c: cdr c
        set l: cdr l
    }
    return: cdr r
}
define glob: builtin (: args) as: return args
define import: syntax e (name) as {
    define m: module name
    if (or (is-null m) (is-object m)) {
        return m
    }

    define l: list 'source name
    set l: cons 'object: cons l '()
    set l: list 'Root::define m l
    e::eval l
}
define is-text: method (t) as: or (is-string t) (is-symbol t)
define object: syntax e (: body) as {
    e::eval: cons 'block: append body '(clone)
}
define or: syntax e (: lst) as {
    define r False
    while (not: is-null: car lst) {
	set r: e::eval: car lst
        if r: return r
        set lst: cdr lst 
    }
    return r
}
define pipe-stderr: $connect pipe $stderr True
define pipe-stdout: $connect pipe $stdout True
define printf: method (: args) as: echo: Text::sprintf (car args) @(cdr args)
define quote: syntax (cell) as: return cell
define read: builtin () as: $stdin::read
define readline: builtin () as: $stdin::readline
define redirect-stderr: $redirect $stderr "w" writer-close
define redirect-stdin: $redirect $stdin "r" reader-close
define redirect-stdout: $redirect $stdout "w" writer-close
define source: syntax e (name) as {
	define basename: e::eval name
	define paths: Text::split ":" $OHPATH
	define name basename

	while (and (not: is-null paths) (not: test -r name)) {
		set name: Text::join / (car paths) basename
		set paths: cdr paths
	}

	if (not: test -r name): set name basename

	define f: open name "r-"
	define l: f::read
	while l {
		e::eval l
		set l: f::read
	}
	f::reader-close
}
define write: method (: args) as: $stdout::write @args

List::public ref: method (k x) as: car: List::tail k x
List::public tail: method (k x) as {
    if k {
        List::tail (sub k 1): cdr x
    } else {
        return x
    }
}

test -r (Text::join / $HOME .ohrc) && source (Text::join / $HOME .ohrc)
`)), Evaluate)
}