diff --git a/core/types.go b/core/types.go index 13f9e1b..34fd1f6 100644 --- a/core/types.go +++ b/core/types.go @@ -21,6 +21,7 @@ const ( TypeComposite TypeInner TypeNamed + TypeRecord ) func (t Type) String() string { @@ -521,3 +522,56 @@ func (s *NamedSignature) Equal(t TypeSignature) bool { func (s *NamedSignature) String() string { return s.Name } + +type RecordSignature struct { + Entries map[string]TypeSignature +} + +func (*RecordSignature) Type() Type { + return TypeRecord +} + +func (s *RecordSignature) Contains(t TypeSignature) bool { + if t.Type() != TypeRecord { + return false + } + + rs := t.(*RecordSignature) + + /* + // not quite sure about this one + if len(s.Entries) != len(rs.Entries) { + return false + } + */ + + for k, v := range s.Entries { + is, ok := rs.Entries[k] + if !ok { + return false + } + + if !v.Contains(is) { + return false + } + } + + return true +} + +func (s *RecordSignature) Equal(t TypeSignature) bool { + return s.Contains(t) && t.Contains(s) +} + +func (s *RecordSignature) String() string { + b := strings.Builder{} + b.WriteString("(") + + for name, kind := range s.Entries { + b.WriteString(fmt.Sprintf("%s: %s, ", name, kind)) + } + + b.WriteString(")") + + return b.String() +} diff --git a/core/values.go b/core/values.go index 94c666f..357c5d2 100644 --- a/core/values.go +++ b/core/values.go @@ -22,7 +22,7 @@ const ( ObjectValueType FunctionValueType BuiltinFunctionValueType - VariableValueType + RecordValueType ) func (v ValueType) String() string { @@ -47,8 +47,8 @@ func (v ValueType) String() string { return "function" case BuiltinFunctionValueType: return "builtin function" - case VariableValueType: - return "variable" + case RecordValueType: + return "record" } return "undefined" @@ -767,3 +767,59 @@ func (v *BuiltinFunctionValue) Clone() Value { v.Constant, } } + +type RecordValue struct { + Entries map[string]Value +} + +func (v *RecordValue) Type() ValueType { + return RecordValueType +} + +func (v *RecordValue) String() string { + return "" +} + +func (v *RecordValue) DebugString() string { + return v.String() +} + +func (v *RecordValue) Clone() Value { + return &RecordValue{ + v.Entries, + } +} + +func (v *RecordValue) Equals(other Value) bool { + if other.Type() != RecordValueType { + return false + } + + r := other.(*RecordValue) + + if len(r.Entries) != len(v.Entries) { + return false + } + + for key, val := range v.Entries { + oth, ok := r.Entries[key] + if !ok { + return false + } + + if !val.Equals(oth) { + return false + } + } + + return true +} + +func (v *RecordValue) Get(key string) (Value, error) { + val, ok := v.Entries[key] + if !ok { + return nil, errors.New(fmt.Sprintf("record has no property \"%s\"", key)) + } + + return val, nil +}