Commit 9211a7d4 authored by Austin Clements's avatar Austin Clements

Beginnings of a Go interpreter. This implements basic and

pointer types, supports literals, identifiers, type-checking
most unary and binary operators, "compiling" a few unary and
binary operators, and assignment and declaration statements.

R=rsc
APPROVED=rsc
DELTA=1751  (1751 added, 0 deleted, 0 changed)
OCL=31309
CL=31691
parent 8071cdf7
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import (
"bignum";
)
/*
* Types
*/
type Type interface {
// literal returns this type with all names recursively
// stripped.
// TODO(austin) Eliminate the need for this
literal() Type;
// compatible returns true if this type is compatible with o.
// XXX Assignment versus comparison compatibility?
compatible(o Type) bool;
// isInteger returns true if this is an integer type.
isInteger() bool;
// isFloat returns true if this is a floating type.
isFloat() bool;
// isIdeal returns true if this is an ideal int or float.
isIdeal() bool;
// String returns the string representation of this type.
String() string;
}
type BoundedType interface {
Type;
// minVal returns the smallest value of this type.
minVal() *bignum.Rational;
// maxVal returns the largest value of this type.
maxVal() *bignum.Rational;
}
/*
* Values
*/
type Value interface {
// TODO(austin) Is Type even necessary?
Type() Type;
String() string;
}
type BoolValue interface {
Value;
Get() bool;
Set(bool);
}
type UintValue interface {
Value;
Get() uint64;
Set(uint64);
}
type IntValue interface {
Value;
Get() int64;
Set(int64);
}
type IdealIntValue interface {
Value;
Get() *bignum.Integer;
}
type FloatValue interface {
Value;
Get() float64;
Set(float64);
}
type IdealFloatValue interface {
Value;
Get() *bignum.Rational;
}
type StringValue interface {
Value;
Get() string;
Set(string);
}
type PtrValue interface {
Value;
Get() Value;
Set(Value);
}
/*
* Scopes
*/
type Variable struct {
// Index of this variable in the Frame structure
Index int;
// Static type of this variable
Type Type;
}
type Constant struct {
// TODO(austin) Need Type?
Type Type;
Value Value;
}
// A definition can be a *Variable, *Constant, or Type.
type Def interface {}
type Scope struct {
outer *Scope;
defs map[string] Def;
numVars int;
}
func NewRootScope() *Scope
func (s *Scope) Fork() *Scope
func (s *Scope) DefineVar(name string, t Type) *Variable
func (s *Scope) DefineConst(name string, v Value) *Constant
func (s *Scope) DefineType(name string, t Type) bool
func (s *Scope) Lookup(name string) (Def, *Scope)
/*
* Frames
*/
type Frame struct {
Outer *Frame;
Scope *Scope;
Vars []Value;
}
This diff is collapsed.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import (
"eval";
)
func NewRootScope() *Scope {
return &Scope{nil, make(map[string] Def), 0};
}
func (s *Scope) Fork() *Scope {
return &Scope{s, make(map[string] Def), 0};
}
func (s *Scope) DefineVar(name string, t Type) *Variable {
if _, ok := s.defs[name]; ok {
return nil;
}
v := &Variable{s.numVars, t};
s.numVars++;
s.defs[name] = v;
return v;
}
func (s *Scope) DefineConst(name string, v Value) *Constant {
if _, ok := s.defs[name]; ok {
return nil;
}
c := &Constant{v.Type(), v};
s.defs[name] = c;
return c;
}
func (s *Scope) DefineType(name string, t Type) bool {
if _, ok := s.defs[name]; ok {
return false;
}
s.defs[name] = t;
return true;
}
func (s *Scope) Lookup(name string) (Def, *Scope) {
for s != nil {
if d, ok := s.defs[name]; ok {
return d, s;
}
s = s.outer;
}
return nil, nil;
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import (
"bignum";
"eval";
)
// XXX(Spec) The type compatibility section is very confusing because
// it makes it seem like there are three distinct types of
// compatibility: plain compatibility, assignment compatibility, and
// comparison compatibility. As I understand it, there's really only
// assignment compatibility and comparison and conversion have some
// restrictions and have special meaning in some cases where the types
// are not otherwise assignment compatible. The comparison
// compatibility section is almost all about the semantics of
// comparison, not the type checking of it, so it would make much more
// sense in the comparison operators section. The compatibility and
// assignment compatibility sections should be rolled into one.
// XXX(Spec) Comparison compatibility: "Values of any type may be
// compared to other values of compatible static type." That should
// be *identical* type.
type commonType struct {
}
func (commonType) isInteger() bool {
return false;
}
func (commonType) isFloat() bool {
return false;
}
func (commonType) isIdeal() bool {
return false;
}
type boolType struct {
commonType;
}
var BoolType Type = &boolType{};
func (t *boolType) literal() Type {
return t;
}
func (t *boolType) compatible(o Type) bool {
return Type(t) == o;
}
func (boolType) String() string {
return "bool";
}
type uintType struct {
commonType;
Bits uint;
// true for uintptr, false for all others
Ptr bool;
name string;
}
// TODO(austin) These are all technically *named types*, which matters
// for some things. Perhaps these should be the underlying unnamed
// types and the named types should be created when they are put in
// the universal scope.
var (
Uint8Type Type = &uintType{commonType{}, 8, false, "uint8"};
Uint16Type Type = &uintType{commonType{}, 16, false, "uint16"};
Uint32Type Type = &uintType{commonType{}, 32, false, "uint32"};
Uint64Type Type = &uintType{commonType{}, 64, false, "uint64"};
UintType Type = &uintType{commonType{}, 64, false, "uint"};
UintptrType Type = &uintType{commonType{}, 64, true, "uintptr"};
)
func (t *uintType) literal() Type {
return t;
}
func (t *uintType) compatible(o Type) bool {
return Type(t) == o;
}
func (t *uintType) isInteger() bool {
return true;
}
func (t *uintType) String() string {
return t.name;
}
func (t *uintType) value(v uint64) UintValue
func (t *uintType) minVal() *bignum.Rational {
return bignum.Rat(0, 1);
}
func (t *uintType) maxVal() *bignum.Rational {
return bignum.MakeRat(bignum.Int(1).Shl(t.Bits).Add(bignum.Int(-1)), bignum.Nat(1));
}
type intType struct {
commonType;
// XXX(Spec) Numeric types: "There is also a set of
// architecture-independent basic numeric types whose size
// depends on the architecture." Should that be
// architecture-dependent?
Bits uint;
name string;
}
var (
Int8Type Type = &intType{commonType{}, 8, "int8"};
Int16Type Type = &intType{commonType{}, 16, "int16"};
Int32Type Type = &intType{commonType{}, 32, "int32"};
Int64Type Type = &intType{commonType{}, 64, "int64"};
IntType Type = &intType{commonType{}, 64, "int"};
)
func (t *intType) literal() Type {
return t;
}
func (t *intType) compatible(o Type) bool {
return Type(t) == o;
}
func (t *intType) isInteger() bool {
return true;
}
func (t *intType) String() string {
return t.name;
}
func (t *intType) value(v int64) IntValue
func (t *intType) minVal() *bignum.Rational {
return bignum.MakeRat(bignum.Int(-1).Shl(t.Bits - 1), bignum.Nat(1));
}
func (t *intType) maxVal() *bignum.Rational {
return bignum.MakeRat(bignum.Int(1).Shl(t.Bits - 1).Add(bignum.Int(-1)), bignum.Nat(1));
}
type idealIntType struct {
commonType;
}
var IdealIntType Type = &idealIntType{}
func (t *idealIntType) literal() Type {
return t;
}
func (t *idealIntType) compatible(o Type) bool {
return Type(t) == o;
}
func (t *idealIntType) isInteger() bool {
return true;
}
func (t *idealIntType) isIdeal() bool {
return true;
}
func (t *idealIntType) String() string {
return "ideal integer";
}
func (t *idealIntType) value(v *bignum.Integer) IdealIntValue
type floatType struct {
commonType;
Bits uint;
}
var (
Float32Type Type = &floatType{commonType{}, 32};
Float64Type Type = &floatType{commonType{}, 64};
FloatType Type = &floatType{commonType{}, 64};
)
func (t *floatType) literal() Type {
return t;
}
func (t *floatType) compatible(o Type) bool {
return Type(t) == o;
}
func (t *floatType) isFloat() bool {
return true;
}
func (t *floatType) String() string {
return "float";
}
func (t *floatType) value(v float64) FloatValue
func (t *floatType) minVal() *bignum.Rational {
panic("Not implemented");
}
func (t *floatType) maxVal() *bignum.Rational {
panic("Not implemented");
}
type idealFloatType struct {
commonType;
}
var IdealFloatType Type = &idealFloatType{};
func (t *idealFloatType) literal() Type {
return t;
}
func (t *idealFloatType) compatible(o Type) bool {
return Type(t) == o;
}
func (t *idealFloatType) isFloat() bool {
return true;
}
func (t *idealFloatType) isIdeal() bool {
return true;
}
func (t *idealFloatType) String() string {
return "ideal float";
}
func (t *idealFloatType) value(v *bignum.Rational) IdealFloatValue
type stringType struct {
commonType;
}
var StringType Type = &stringType{};
func (t *stringType) literal() Type {
return t;
}
func (t *stringType) compatible(o Type) bool {
return Type(t) == o;
}
func (t *stringType) String() string {
return "string";
}
func (t *stringType) value(v string) StringValue
/*
type ArrayType struct {
commonType;
elem Type;
}
func (t *ArrayType) literal() Type {
// TODO(austin)
}
type StructType struct {
commonType;
Names map[string] Name;
}
*/
type PtrType struct {
commonType;
elem Type;
lit Type;
}
var ptrTypes = make(map[Type] *PtrType)
func NewPtrType(elem Type) *PtrType {
t, ok := ptrTypes[elem];
if !ok {
t = &PtrType{commonType{}, elem, nil};
ptrTypes[elem] = t;
}
return t;
}
func (t *PtrType) Elem() Type {
return t.elem;
}
func (t *PtrType) literal() Type {
if t.lit == nil {
t.lit = NewPtrType(t.elem.literal());
}
return t.lit;
}
func (t *PtrType) compatible(o Type) bool {
return t.literal() == o.literal();
}
func (t *PtrType) String() string {
return "*" + t.elem.String();
}
func (t *PtrType) value(v Value) PtrValue
/*
type FuncType struct {
commonType;
// TODO(austin)
}
func (t *FuncType) literal() Type {
// TODO(austin)
}
type InterfaceType struct {
// TODO(austin)
}
type SliceType struct {
// TODO(austin)
}
type MapType struct {
// TODO(austin)
}
type ChanType struct {
// TODO(austin)
}
type NamedType struct {
// Declaration scope
scope *Scope;
name string;
// Underlying type
def Type;
// TODO(austin) Methods can be on NamedType or *NamedType
methods map[string] XXX;
}
func (t *NamedType) literal() Type {
return t.def.literal();
}
func (t *NamedType) isInteger() bool {
return t.isInteger();
}
*/
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import (
"bignum";
"eval";
"fmt";
"go/token";
)
// TODO(austin): Maybe add to bignum in more general form
func ratToString(rat *bignum.Rational) string {
n, dnat := rat.Value();
d := bignum.MakeInt(false, dnat);
w, frac := n.QuoRem(d);
out := w.String();
if frac.IsZero() {
return out;
}
r := frac.Abs();
r = r.Mul(bignum.Nat(1e6));
dec, tail := r.DivMod(dnat);
// Round last digit
if tail.Cmp(dnat.Div(bignum.Nat(2))) >= 0 {
dec = dec.Add(bignum.Nat(1));
}
// Strip zeros
ten := bignum.Nat(10);
for !dec.IsZero() {
dec2, r2 := dec.DivMod(ten);
if !r2.IsZero() {
break;
}
dec = dec2;
}
out += "." + dec.String();
return out;
}
func diag(p token.Position, format string, args ...) {
if p.IsValid() {
fmt.Printf("%s:%d.%d: ", p.Filename, p.Line, p.Column);
}
fmt.Printf(format, args);
fmt.Print("\n");
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import (
"bignum";
"eval";
"fmt";
)
/*
* Bool
*/
type boolV bool
func (*boolV) Type() Type {
return BoolType;
}
func (v *boolV) String() string {
return fmt.Sprint(*v);
}
func (v *boolV) Get() bool {
return bool(*v);
}
func (v *boolV) Set(x bool) {
*v = boolV(x);
}
/*
* Uint
*/
type uint8V uint8
func (*uint8V) Type() Type {
return Uint8Type;
}
func (v *uint8V) String() string {
return fmt.Sprint(*v);
}
func (v *uint8V) Get() uint64 {
return uint64(*v);
}
func (v *uint8V) Set(x uint64) {
*v = uint8V(x);
}
type uint16V uint16
func (*uint16V) Type() Type {
return Uint16Type;
}
func (v *uint16V) String() string {
return fmt.Sprint(*v);
}
func (v *uint16V) Get() uint64 {
return uint64(*v);
}
func (v *uint16V) Set(x uint64) {
*v = uint16V(x);
}
type uint32V uint32
func (*uint32V) Type() Type {
return Uint32Type;
}
func (v *uint32V) String() string {
return fmt.Sprint(*v);
}
func (v *uint32V) Get() uint64 {
return uint64(*v);
}
func (v *uint32V) Set(x uint64) {
*v = uint32V(x);
}
type uint64V uint64
func (*uint64V) Type() Type {
return Uint64Type;
}
func (v *uint64V) String() string {
return fmt.Sprint(*v);
}
func (v *uint64V) Get() uint64 {
return uint64(*v);
}
func (v *uint64V) Set(x uint64) {
*v = uint64V(x);
}
type uintV uint
func (*uintV) Type() Type {
return UintType;
}
func (v *uintV) String() string {
return fmt.Sprint(*v);
}
func (v *uintV) Get() uint64 {
return uint64(*v);
}
func (v *uintV) Set(x uint64) {
*v = uintV(x);
}
type uintptrV uintptr
func (*uintptrV) Type() Type {
return UintptrType;
}
func (v *uintptrV) String() string {
return fmt.Sprint(*v);
}
func (v *uintptrV) Get() uint64 {
return uint64(*v);
}
func (v *uintptrV) Set(x uint64) {
*v = uintptrV(x);
}
func (t *uintType) value(v uint64) UintValue {
// TODO(austin) This executes are run-time, even though
// virtually all of the logic can be done at type-check time.
// TODO(austin) Deal with named types
switch Type(t) {
case Uint8Type:
res := uint8V(v);
return &res;
case Uint16Type:
res := uint16V(v);
return &res;
case Uint32Type:
res := uint32V(v);
return &res;
case Uint64Type:
res := uint64V(v);
return &res;
case UintType:
res := uintV(v);
return &res;
case UintptrType:
res := uintptrV(v);
return &res;
}
panic("unknown uint type ", t.String());
}
/*
* Int
*/
type int8V int8
func (*int8V) Type() Type {
return Int8Type;
}
func (v *int8V) String() string {
return fmt.Sprint(*v);
}
func (v *int8V) Get() int64 {
return int64(*v);
}
func (v *int8V) Set(x int64) {
*v = int8V(x);
}
type int16V int16
func (*int16V) Type() Type {
return Int16Type;
}
func (v *int16V) String() string {
return fmt.Sprint(*v);
}
func (v *int16V) Get() int64 {
return int64(*v);
}
func (v *int16V) Set(x int64) {
*v = int16V(x);
}
type int32V int32
func (*int32V) Type() Type {
return Int32Type;
}
func (v *int32V) String() string {
return fmt.Sprint(*v);
}
func (v *int32V) Get() int64 {
return int64(*v);
}
func (v *int32V) Set(x int64) {
*v = int32V(x);
}
type int64V int64
func (*int64V) Type() Type {
return Int64Type;
}
func (v *int64V) String() string {
return fmt.Sprint(*v);
}
func (v *int64V) Get() int64 {
return int64(*v);
}
func (v *int64V) Set(x int64) {
*v = int64V(x);
}
type intV int
func (*intV) Type() Type {
return IntType;
}
func (v *intV) String() string {
return fmt.Sprint(*v);
}
func (v *intV) Get() int64 {
return int64(*v);
}
func (v *intV) Set(x int64) {
*v = intV(x);
}
func (t *intType) value(v int64) IntValue {
switch Type(t) {
case Int8Type:
res := int8V(v);
return &res;
case Int16Type:
res := int16V(v);
return &res;
case Int32Type:
res := int32V(v);
return &res;
case Int64Type:
res := int64V(v);
return &res;
case IntType:
res := intV(v);
return &res;
}
panic("unknown int type ", t.String());
}
/*
* Ideal int
*/
type idealIntV struct {
V *bignum.Integer;
}
func (*idealIntV) Type() Type {
return IdealIntType;
}
func (v *idealIntV) String() string {
return v.V.String();
}
func (v *idealIntV) Get() *bignum.Integer {
return v.V;
}
func (t *idealIntType) value(v *bignum.Integer) IdealIntValue {
return &idealIntV{v};
}
/*
* Float
*/
type float32V float32
func (*float32V) Type() Type {
return Float32Type;
}
func (v *float32V) String() string {
return fmt.Sprint(*v);
}
func (v *float32V) Get() float64 {
return float64(*v);
}
func (v *float32V) Set(x float64) {
*v = float32V(x);
}
type float64V float64
func (*float64V) Type() Type {
return Float64Type;
}
func (v *float64V) String() string {
return fmt.Sprint(*v);
}
func (v *float64V) Get() float64 {
return float64(*v);
}
func (v *float64V) Set(x float64) {
*v = float64V(x);
}
type floatV float
func (*floatV) Type() Type {
return FloatType;
}
func (v *floatV) String() string {
return fmt.Sprint(*v);
}
func (v *floatV) Get() float64 {
return float64(*v);
}
func (v *floatV) Set(x float64) {
*v = floatV(x);
}
func (t *floatType) value(v float64) FloatValue {
switch Type(t) {
case Float32Type:
res := float32V(v);
return &res;
case Float64Type:
res := float64V(v);
return &res;
case FloatType:
res := floatV(v);
return &res;
}
panic("unknown float type ", t.String());
}
/*
* Ideal float
*/
type idealFloatV struct {
V *bignum.Rational;
}
func (*idealFloatV) Type() Type {
return IdealFloatType;
}
func (v *idealFloatV) String() string {
return ratToString(v.V);
}
func (v *idealFloatV) Get() *bignum.Rational {
return v.V;
}
func (t *idealFloatType) value(v *bignum.Rational) IdealFloatValue {
return &idealFloatV{v};
}
/*
* String
*/
type stringV string
func (*stringV) Type() Type {
return StringType;
}
func (v *stringV) String() string {
return fmt.Sprint(*v);
}
func (v *stringV) Get() string {
return string(*v);
}
func (v *stringV) Set(x string) {
*v = stringV(x);
}
func (t *stringType) value(v string) StringValue {
res := stringV(v);
return &res;
}
/*
* Pointer
*/
type ptrV struct {
// nil if the pointer is nil
target Value;
}
func (v *ptrV) Type() Type {
return NewPtrType(v.target.Type());
}
func (v *ptrV) String() string {
return "&" + v.target.String();
}
func (v *ptrV) Get() Value {
return v.target;
}
func (v *ptrV) Set(x Value) {
v.target = x;
}
func (t *PtrType) value(v Value) PtrValue {
res := ptrV{v};
return &res;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment