Beispiel #1
0
// Stat calculates statistics for all runes read from r.
func (m *Main) Stat(r io.RuneReader) (Stats, error) {
	var stats Stats

	for {
		// Read next character.
		ch, sz, err := r.ReadRune()
		if err == io.EOF {
			break
		} else if err != nil {
			return stats, err
		}

		// Calculate stats.
		stats.TotalN++
		if unicode.IsControl(ch) {
			stats.ControlN++
		}
		if unicode.IsDigit(ch) {
			stats.DigitN++
		}
		if unicode.IsGraphic(ch) {
			stats.GraphicN++
		}
		if unicode.IsLetter(ch) {
			stats.LetterN++
		}
		if unicode.IsLower(ch) {
			stats.LowerN++
		}
		if unicode.IsMark(ch) {
			stats.MarkN++
		}
		if unicode.IsNumber(ch) {
			stats.NumberN++
		}
		if unicode.IsPrint(ch) {
			stats.PrintN++
		}
		if unicode.IsPunct(ch) {
			stats.PunctN++
		}
		if unicode.IsSpace(ch) {
			stats.SpaceN++
		}
		if unicode.IsSymbol(ch) {
			stats.SymbolN++
		}
		if unicode.IsTitle(ch) {
			stats.TitleN++
		}
		if unicode.IsUpper(ch) {
			stats.UpperN++
		}
		if sz > 1 {
			stats.MultiByteN++
		}
	}

	return stats, nil
}
Beispiel #2
0
//IsTitled reports wheter s is in Title Case.
func IsTitled(s string) bool {
	for i, r := range s {
		if i == 0 {
			if !(unicode.IsUpper(r) || unicode.IsTitle(r)) {
				return false
			}
		} else {
			if !unicode.IsLower(r) {
				return false
			}
		}
	}
	return true
}
Beispiel #3
0
func print_rune_types(char rune) {
	if unicode.IsControl(char) {
		fmt.Println("   Control")
	}
	if unicode.IsDigit(char) {
		fmt.Println("   Digit")
	}
	if unicode.IsGraphic(char) {
		fmt.Println("   Graphic")
	}
	if unicode.IsLetter(char) {
		fmt.Println("   Letter")
	}
	if unicode.IsLower(char) {
		fmt.Println("   Lower")
	}
	if unicode.IsMark(char) {
		fmt.Println("   Mark")
	}
	if unicode.IsPrint(char) {
		fmt.Println("   Print")
	}
	if unicode.IsPunct(char) {
		fmt.Println("   Punct")
	}
	if unicode.IsSpace(char) {
		fmt.Println("   Space")
	}
	if unicode.IsSymbol(char) {
		fmt.Println("   Symbol")
	}
	if unicode.IsTitle(char) {
		fmt.Println("   Title")
	}
	if unicode.IsUpper(char) {
		fmt.Println("   Upper")
	}
}
Beispiel #4
0
func propCased(r rune) bool {
	return propLower(r) || propUpper(r) || unicode.IsTitle(r)
}
Beispiel #5
0
func bindStringPredicates(e *Env) {

	e.Method("is-control", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsControl(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("is-digit", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsDigit(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("is-graphic", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsGraphic(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("is-letter", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsLetter(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("is-lower", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsLower(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("is-mark", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsMark(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("is-print", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsPrint(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("is-punct", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsPunct(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("is-space", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsSpace(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("is-symbol", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsSymbol(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("is-title", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsTitle(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("is-upper", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		for _, c := range s {
			if !unicode.IsUpper(c) {
				return t.Return(False)
			}
		}

		return t.Return(True)
	})

	e.Method("to-lower", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		return t.Return(NewString(t, strings.ToLower(s)))
	})

	e.Method("to-title", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		return t.Return(NewString(t, strings.ToTitle(s)))
	})

	e.Method("to-upper", func(t *Task, args Cell) bool {
		s := raw(toString(Car(t.Scratch).(Binding).Self()))

		return t.Return(NewString(t, strings.ToUpper(s)))
	})
}
Beispiel #6
0
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)
	}
}
Beispiel #7
0
func verifyCased(r rune) bool {
	return verifyLower(r) || verifyUpper(r) || unicode.IsTitle(r)
}
func main() {
	counts := make(map[rune]int)          // counts of Unicode characters
	classfication := make(map[string]int) // counts of Unicode classification
	var utflen [utf8.UTFMax + 1]int       // count of lengths of UTF-8 encodings
	invalid := 0                          // count of invalid UTF-8 characters

	in := bufio.NewReader(os.Stdin)
	for {
		r, n, err := in.ReadRune() // returns rune, nbytes, error
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Fprintf(os.Stderr, "charcount: %v\n", err)
			os.Exit(1)
		}
		if r == unicode.ReplacementChar && n == 1 {
			invalid++
			continue
		}

		if unicode.IsControl(r) {
			classfication["Control"]++
		}
		if unicode.IsDigit(r) {
			classfication["Digit"]++
		}
		if unicode.IsGraphic(r) {
			classfication["Graphic"]++
		}
		if unicode.IsLetter(r) {
			classfication["Letter"]++
		}
		if unicode.IsLower(r) {
			classfication["Lower"]++
		}
		if unicode.IsMark(r) {
			classfication["Mark"]++
		}
		if unicode.IsNumber(r) {
			classfication["Number"]++
		}
		if unicode.IsPrint(r) {
			classfication["Print"]++
		}
		if unicode.IsPunct(r) {
			classfication["Punct"]++
		}
		if unicode.IsSpace(r) {
			classfication["Space"]++
		}
		if unicode.IsSymbol(r) {
			classfication["Symbol"]++
		}
		if unicode.IsTitle(r) {
			classfication["Title"]++
		}
		if unicode.IsUpper(r) {
			classfication["Upper"]++
		}

		counts[r]++
		utflen[n]++
	}
	fmt.Printf("rune\tcount\n")
	for c, n := range counts {
		fmt.Printf("%q\t%d\n", c, n)
	}
	fmt.Print("\nlen\tcount\n")
	for i, n := range utflen {
		if i > 0 {
			fmt.Printf("%d\t%d\n", i, n)
		}
	}
	fmt.Print("\nclassification\tcount\n")
	for cls, n := range classfication {
		fmt.Printf("%s\t%d\n", cls, n)
	}
	if invalid > 0 {
		fmt.Printf("\n%d invalid UTF-8 characters\n", invalid)
	}
}
Beispiel #9
0
func Text(b []byte, stripSpeechmarks bool) []byte {

	// Convert to slice of runes
	n := len(b)
	if n == 0 {
		return b
	}
	para := make([][][]rune, 0, 1)
	sent := make([][]rune, 0, 3)
	word := make([]rune, 0, 3)
	var r, lastr rune
	var i, w int
	var ok bool
	for i = 0; i < n; i += w {
		r, w = utf8.DecodeRune(b[i:])

		switch r {
		// New word
		case ' ', 9:
			if len(word) == 0 {
				continue
			}
			sent = append(sent, word)
			word = make([]rune, 0, 3)
			continue
		// New line
		case 10, 13:
			ok = false
			switch lastr {
			case '.', '!', '?':
				ok = true
			}
			if ok {
				if len(sent) == 0 {
					continue
				}
				if len(word) > 0 {
					sent = append(sent, word)
					word = make([]rune, 0, 3)
				}
				para = append(para, sent)
				sent = make([][]rune, 0, 3)
			} else {
				if len(word) == 0 {
					continue
				}
				sent = append(sent, word)
				word = make([]rune, 0, 3)
			}
			continue
		// Normalize aprostrophes
		case '‘', '’':
			r = 39
		// Normalize speechmarks, or stripSpeechmarks
		case '“', '”', '"':
			if stripSpeechmarks {
				continue
			}
			r = '"'
		// em-dash should always be its own word
		case '—':
			if len(word) > 0 {
				sent = append(sent, word)
			}
			sent = append(sent, []rune{'—'})
			word = make([]rune, 0, 3)
			continue
		}

		if r > 127 {
			switch r {
			case 'Æ':
				r = 'e'
			case 'æ':
				r = 'e'
			case 'Œ':
				word = append(word, 'o')
				r = 'e'
			case 'œ':
				word = append(word, 'o')
				r = 'e'
			case 'fi':
				word = append(word, 'f')
				r = 'i'
			}
		}

		// Add rune
		word = append(word, r)
		lastr = r
	}
	if len(word) > 0 {
		sent = append(sent, word)
	}
	if len(sent) > 0 {
		para = append(para, sent)
	}

	numpara := len(para)
	var allcaps, firstcap, othercap, anyletter, puncbefore bool
	var last, i2, on int
	for i = 0; i < numpara; i++ {
		sent = para[i]

		puncbefore = true
		// Loop though each word and correct casing
		for on, word = range sent {

			// First check for lost punctuation in front of the word
			ok = true
			for i2, r = range word {
				if unicode.IsLetter(r) || unicode.IsNumber(r) {
					break
				}
				switch r {
				case ',', '.', ':', ';', '!':
					ok = false
				}
			}
			if !ok {
				if on > 0 && !puncbefore && unicode.IsLetter(r) && (unicode.IsUpper(r) || unicode.IsTitle(r)) {
					sent[on-1] = append(sent[on-1], word[0:i2]...)
					puncbefore = true
				}
				sent[on] = word[i2:]
				word = word[i2:]
			}

			// Calculate the casing type of the word
			r = word[0]
			othercap = false
			if unicode.IsLetter(r) {
				anyletter = true
				if unicode.IsUpper(r) || unicode.IsTitle(r) {
					allcaps = true
					firstcap = true
				} else {
					allcaps = false
					firstcap = false
				}
			} else {
				anyletter = false
				allcaps = false
				firstcap = false
			}
			for _, r = range word[1:] {
				if unicode.IsLetter(r) {
					anyletter = true
					if unicode.IsUpper(r) || unicode.IsTitle(r) {
						othercap = true
					} else {
						allcaps = false
					}
				}
			}
			if anyletter {
				if puncbefore {
					if !firstcap {
						upperfirst(word)
					} else {
						if allcaps {
							if !isException(word) {
								upperfirst(word)
							}
						} else {
							if othercap {
								upperfirst(word)
							}
						}
					}
				} else {
					if othercap {
						if allcaps {
							if !isException(word) {
								lowercase(word)
							}
						} else {
							lowercase(word)
						}
					}
				}
			}

			puncbefore = false
			for i2 = len(word) - 1; i2 >= 0; i2-- {
				r = r
				if unicode.IsPunct(r) {
					switch r {
					case '.', '?', '!':
						puncbefore = true
						break
					}
				} else {
					break
				}
			}

		}

		// Ensure last character is suitable
		word = sent[len(sent)-1]
		last = len(word) - 1
		ok = false
		r = word[last]
		switch r {
		case '.', '!', '?', ')', '"', 39:
			ok = true
		}
		if !ok {
			if !unicode.IsPunct(r) {
				sent[len(sent)-1] = append(sent[len(sent)-1], '.')
			} else {
				for i2 = last - 1; i2 >= 0; i2-- {
					r = word[i2]
					switch r {
					case '.', '!', '?', ')', '"', 39:
						sent[len(sent)-1] = sent[len(sent)-1][0 : i2+1]
						break
					}
					if !unicode.IsPunct(r) {
						word[i2+1] = '.'
						sent[len(sent)-1] = sent[len(sent)-1][0 : i2+2]
						break
					}
				}
			}
		}
	}

	// Write it back
	buf := bytes.NewBuffer(make([]byte, 0, 20))
	for i, sent = range para {
		if i > 0 {
			buf.WriteByte(10)
			if len(sent) > 10 {
				buf.WriteByte(10)
			}
		}
		for i2, word = range sent {
			if i2 > 0 {
				buf.WriteByte(' ')
			}
			for _, r = range word {
				buf.WriteRune(r)
			}
		}
	}
	return buf.Bytes()

}
Beispiel #10
0
// Functions starting with "Is" can be used to inspect which table of range a
// rune belongs to. Note that runes may fit into more than one range.
func Example_is() {

	// constant with mixed type runes
	const mixed = "\b5Ὂg̀9! ℃ᾭG"
	for _, c := range mixed {
		fmt.Printf("For %q:\n", c)
		if unicode.IsControl(c) {
			fmt.Println("\tis control rune")
		}
		if unicode.IsDigit(c) {
			fmt.Println("\tis digit rune")
		}
		if unicode.IsGraphic(c) {
			fmt.Println("\tis graphic rune")
		}
		if unicode.IsLetter(c) {
			fmt.Println("\tis letter rune")
		}
		if unicode.IsLower(c) {
			fmt.Println("\tis lower case rune")
		}
		if unicode.IsMark(c) {
			fmt.Println("\tis mark rune")
		}
		if unicode.IsNumber(c) {
			fmt.Println("\tis number rune")
		}
		if unicode.IsPrint(c) {
			fmt.Println("\tis printable rune")
		}
		if !unicode.IsPrint(c) {
			fmt.Println("\tis not printable rune")
		}
		if unicode.IsPunct(c) {
			fmt.Println("\tis punct rune")
		}
		if unicode.IsSpace(c) {
			fmt.Println("\tis space rune")
		}
		if unicode.IsSymbol(c) {
			fmt.Println("\tis symbol rune")
		}
		if unicode.IsTitle(c) {
			fmt.Println("\tis title case rune")
		}
		if unicode.IsUpper(c) {
			fmt.Println("\tis upper case rune")
		}
	}

	// Output:
	// For '\b':
	// 	is control rune
	// 	is not printable rune
	// For '5':
	// 	is digit rune
	// 	is graphic rune
	// 	is number rune
	// 	is printable rune
	// For 'Ὂ':
	// 	is graphic rune
	// 	is letter rune
	// 	is printable rune
	// 	is upper case rune
	// For 'g':
	// 	is graphic rune
	// 	is letter rune
	// 	is lower case rune
	// 	is printable rune
	// For '̀':
	// 	is graphic rune
	// 	is mark rune
	// 	is printable rune
	// For '9':
	// 	is digit rune
	// 	is graphic rune
	// 	is number rune
	// 	is printable rune
	// For '!':
	// 	is graphic rune
	// 	is printable rune
	// 	is punct rune
	// For ' ':
	// 	is graphic rune
	// 	is printable rune
	// 	is space rune
	// For '℃':
	// 	is graphic rune
	// 	is printable rune
	// 	is symbol rune
	// For 'ᾭ':
	// 	is graphic rune
	// 	is letter rune
	// 	is printable rune
	// 	is title case rune
	// For 'G':
	// 	is graphic rune
	// 	is letter rune
	// 	is printable rune
	// 	is upper case rune
}
Beispiel #11
0
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)
}