gocc icon indicating copy to clipboard operation
gocc copied to clipboard

Make typeMap/idMap publicly accessible

Open Happy-Ferret opened this issue 5 years ago • 5 comments

Curious.

Any good reason against making typeMap and idMap public, so its contents can be accessed by the consumer?

I've spent the past 6 hours trying to painfully retrieve a Type's index from idMap through reflection, and I'm still not close to a solution.

If it was IdMap instead, one could simply loop over it and retrieve the index like so:

	for i, k := range token.TokMap.IdMap {
		switch k {
		case intLit.Type:
			fmt.Println(i)
		}
	}

Happy-Ferret avatar Jul 02 '19 06:07 Happy-Ferret

What do you want to use it for?

On Tue, 2 Jul 2019 at 07:29, Happy-Ferret [email protected] wrote:

Curious.

Any good reason against making typeMap https://github.com/goccmack/gocc/blob/master/internal/token/gen/golang/token.go#L90 and idMap public, so its contents can be accessed by the consumer?

I've spent the past 6 hours trying to painfully retrieve a Type's index from idMap through reflection, and I'm still not close to a solution.

If it was IdMap instead, one could simply loop over it and retrieve the index like so:

for i, k := range token.TokMap.IdMap { switch k { case intLit.Type: fmt.Println(i) } }

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/goccmack/gocc/issues/92?email_source=notifications&email_token=AAN6YLL4ZKIUNPCCNWRHRNTP5LYTNA5CNFSM4H4YOEHKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4G4ZQFPA, or mute the thread https://github.com/notifications/unsubscribe-auth/AAN6YLPX2ZBVPX7CKWILRW3P5LYTNANCNFSM4H4YOEHA .

awalterschulze avatar Jul 02 '19 07:07 awalterschulze

NVM. After some head scratching it turned out to be much easier than I had thought.

t := reflect.ValueOf(token.TokMap)
v := t.FieldByName("typeMap").Index(int(intLit.Type))

// Prints integer type
println(v)

I'm in the process of writing a small language compiler and needed that information for the debug output.

Here's the full -- quick and dirty. I'm, obviously, going to make it generic for types other than int32 -- implementation of catching an overflow (message is my own package for outputting compiler errors. I didn't like the verbose output of the gocc generated errors package):

func NewIntegerLiteral(integer Attrib) (Expression, error) {
	intLit, ok := integer.(*token.Token)
	if !ok {
		return nil, Error("NewIntegerLiteral", "*token.Token", "integer", integer)
	}

	maxInt := 0x7fffffff
	minInt := -0x80000000
	number, _ := strconv.Atoi(string(intLit.Lit))

	if number > maxInt || number < minInt {
		t := reflect.ValueOf(token.TokMap)
		v := t.FieldByName("typeMap").Index(int(intLit.Type))

		message.Errorf("Arithmetic overflow detected! %v overflows %v (Line: %v, Column: %v)", number, v, intLit.Pos.Line, intLit.Pos.Column)
	}

	return &IntegerLiteral{Token: intLit, Value: string(intLit.Lit)}, nil
}

Happy-Ferret avatar Jul 02 '19 07:07 Happy-Ferret

Very interesting.

Why print out the error, instead of returning it?

Warning: I don’t know if FieldByName works for private fields for all versions of Go.

On Tue, 2 Jul 2019 at 08:30, Happy-Ferret [email protected] wrote:

NVM. After some head scratching it turned out to be much easier than I had thought.

t := reflect.ValueOf(token.TokMap)v := t.FieldByName("typeMap").Index(int(intLit.Type)) // Prints integer typeprintln(v)

I'm in the process of writing a small language compiler and needed that information for the debug output.

Here's the full -- quick and dirty. I'm, obviously, going to make it generic for types other than int32 -- implementation of catching an overflow (message is my own package for outputting compiler errors. I didn't like the verbose output of the gocc generated errors package):

func NewIntegerLiteral(integer Attrib) (Expression, error) { intLit, ok := integer.(*token.Token) if !ok { return nil, Error("NewIntegerLiteral", "*token.Token", "integer", integer) }

maxInt := 0x7fffffff minInt := -0x80000000 number, _ := strconv.Atoi(string(intLit.Lit))

if number > maxInt || number < minInt { t := reflect.ValueOf(token.TokMap) v := t.FieldByName("typeMap").Index(int(intLit.Type))

  message.Errorf("Arithmetic overflow detected! %v overflows %v (Line: %v, Column: %v)", number, v, intLit.Pos.Line, intLit.Pos.Column)

}

return &IntegerLiteral{Token: intLit, Value: string(intLit.Lit)}, nil }

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/goccmack/gocc/issues/92?email_source=notifications&email_token=AAN6YLMZHPIPFJSYBERI64LP5L7Z7A5CNFSM4H4YOEHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODZALFOI#issuecomment-507556537, or mute the thread https://github.com/notifications/unsubscribe-auth/AAN6YLPPCR4ZW4L6LEPQ4ZLP5L7Z7ANCNFSM4H4YOEHA .

awalterschulze avatar Jul 02 '19 07:07 awalterschulze

Why print out the error, instead of returning it?

Admittedly, because this project makes me feel like an utter newbie.

If I simply return the error with fmt.Errorf, the output is formatted to: ERROR Error in S21: sub(15,-), Pos(offset=284, line=14, column=21): Arithmetic overflow detected! -2147483649 overflows int (Line: 14, Column: 9)

So my message package looks like this instead:

package message

import (
	"fmt"
	"os"

	colorable "github.com/mattn/go-colorable"
	"github.com/sirupsen/logrus"
)

func init() {
	timestampFormat := "Mon Jan 2 15:04:05 -0700 MST 2006"
	var disableTimestamp bool

	if len(os.Getenv("TCTimestamp")) == 1 {
		disableTimestamp = false
	} else {
		disableTimestamp = true
	}
	logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true, DisableLevelTruncation: true, DisableTimestamp: disableTimestamp, FullTimestamp: true, TimestampFormat: timestampFormat})
	logrus.SetOutput(colorable.NewColorableStdout())
}

// Error throws an error and aborts the running process.
func Error(v interface{}) {
	logrus.Error(v)
	os.Exit(1)
}

// Errorf formats an error message according to a format specifier,
// throws the error and aborts the running process.
func Errorf(format string, v ...interface{}) {
	logrus.Error(fmt.Sprintf(format, v...))
	os.Exit(1)
}

// Warning displays a warning log message.
func Warning(v interface{}) {
	logrus.Warning(v)
}

// Info displays an informational log message.
func Info(v interface{}) {
	logrus.Info(v)
}

Happy-Ferret avatar Jul 02 '19 08:07 Happy-Ferret

You can still return the error log it after parsing, instead of logging it at the moment of the failure.

awalterschulze avatar Jul 06 '19 18:07 awalterschulze