Dingo - A meta-language for Go

2 min read Original article ↗

Dingo

Dingo mascot peeking

// Test: Nested sum types (interface-based enum)
// Feature: Sum types with nested enum variants
// Complexity: advanced
package main

import "errors"

enum Result {
	Ok(Value),
	Err(error),
}

enum Value {
	Int(int),
	String(string),
	None,
}

func parseInt(s string) Result {
	if s == "" {
		return NewResultErr(errors.New("empty string"))
	}
	if s == "null" {
		return NewResultOk(NewValueNone())
	}
	return NewResultOk(NewValueString(s))
}

func main() {
	result := parseInt("hello")
	switch r := result.(type) {
	case ResultOk:
		switch v := r.Value.(type) {
		case ValueString:
			println("String:", v.Value)
		}
	}
}

Go

Go Gopher peeking

package main

import "errors"

// Test: Nested sum types
// Feature: Sum types with nested enum variants
// Complexity: advanced


type ResultTag uint8

const (
	ResultTagOk ResultTag = iota
	ResultTagErr
)

type Result struct {
	tag ResultTag
	err *error
	ok  *Value
}

func ResultOk(arg0 Value) Result {
	return Result{tag: ResultTagOk, ok: &arg0}
}
func ResultErr(arg0 error) Result {
	return Result{tag: ResultTagErr, err: &arg0}
}
func (e Result) IsOk() bool {
	return e.tag == ResultTagOk
}
func (e Result) IsErr() bool {
	return e.tag == ResultTagErr
}
func (r Result) Map(fn func(Value) Value) Result {
	switch r.tag {
	case ResultTagOk:
		if r.ok != nil {
			return ResultOk(fn(*r.ok))
		}
	case ResultTagErr:
		return r
	}
	panic("invalid Result state")
}
func (r Result) AndThen(fn func(Value) Result) Result {
	switch r.tag {
	case ResultTagOk:
		if r.ok != nil {
			return fn(*r.ok)
		}
	case ResultTagErr:
		return r
	}
	panic("invalid Result state")
}


type ValueTag uint8

const (
	ValueTagInt ValueTag = iota
	ValueTagString
	ValueTagNone
)

type Value struct {
	tag    ValueTag
	int    *int
	string *string
}
func ValueInt(arg0 int) Value {
	return Value{tag: ValueTagInt, int: &arg0}
}
func ValueString(arg0 string) Value {
	return Value{tag: ValueTagString, string: &arg0}
}
func ValueNone() Value {
	return Value{tag: ValueTagNone}
}
func (e Value) IsInt() bool {
	return e.tag == ValueTagInt
}
func (e Value) IsString() bool {
	return e.tag == ValueTagString
}
func (e Value) IsNone() bool {
	return e.tag == ValueTagNone
}
func parseInt(s string) Result {
	if s == "" {
		return ResultErr(errors.New("empty string"))
	}
	if s == "null" {
		return ResultOk(ValueNone())
	}
	return ResultOk(ValueString(s))
}
func main() {
	result := parseInt("hello")
	if result.IsOk() {
		value := *result.ok
		if value.IsString() {
			println("String:", *value.string_0)
		}
	}
}