<commit_before>package compile

import (
	"../ast"
	"../ir"
	"../vm"
	"./env"
	"fmt"
	"log"
)

type compiler struct {
	env env.Environment
}

func newCompiler() compiler {
	return compiler{env: prelude.Child()}
}

func (c *compiler) compile(module []interface{}) []*vm.Thunk {
	outputs := make([]*vm.Thunk, 0, 8) // TODO: Best cap?

	for _, node := range module {
		switch x := node.(type) {
		case ast.LetConst:
			c.env.Set(x.Name(), c.exprToThunk(x.Expr()))
		case ast.LetFunction:
			c.env.Set(x.Name(), ir.CompileFunction(c.compileSignature(x.Signature()), c.exprToIR(x.Signature(), x.Body())))
		case ast.Output:
			outputs = append(outputs, c.exprToThunk(x.Expr()))
		default:
			panic(fmt.Sprint("Invalid instruction.", x))
		}
	}

	return outputs
}

func (c *compiler) exprToThunk(expr interface{}) *vm.Thunk {
	switch x := expr.(type) {
	case string:
		return getOrError(c.env, x)
	case ast.App:
		args := x.Arguments()

		ps := make([]vm.PositionalArgument, len(args.Positionals()))
		for i, p := range args.Positionals() {
			ps[i] = vm.NewPositionalArgument(c.exprToThunk(p.Value()), p.Expanded())
		}

		ks := make([]vm.KeywordArgument, len(args.Keywords()))
		for i, k := range args.Keywords() {
			ks[i] = vm.NewKeywordArgument(k.Name(), c.exprToThunk(k.Value()))<commit_msg>Add todo on expanded outputs<commit_after>package compile

import (
	"../ast"
	"../ir"
	"../vm"
	"./env"
	"fmt"
	"log"
)

type compiler struct {
	env env.Environment
}

func newCompiler() compiler {
	return compiler{env: prelude.Child()}
}

func (c *compiler) compile(module []interface{}) []*vm.Thunk {
	outputs := make([]*vm.Thunk, 0, 8) // TODO: Use ListType.

	for _, node := range module {
		switch x := node.(type) {
		case ast.LetConst:
			c.env.Set(x.Name(), c.exprToThunk(x.Expr()))
		case ast.LetFunction:
			c.env.Set(x.Name(), ir.CompileFunction(c.compileSignature(x.Signature()), c.exprToIR(x.Signature(), x.Body())))
		case ast.Output:
			outputs = append(outputs, c.exprToThunk(x.Expr())) // TODO: Expand expanded lists.
		default:
			panic(fmt.Sprint("Invalid instruction.", x))
		}
	}

	return outputs
}

func (c *compiler) exprToThunk(expr interface{}) *vm.Thunk {
	switch x := expr.(type) {
	case string:
		return getOrError(c.env, x)
	case ast.App:
		args := x.Arguments()

		ps := make([]vm.PositionalArgument, len(args.Positionals()))
		for i, p := range args.Positionals() {
			ps[i] = vm.NewPositionalArgument(c.exprToThunk(p.Value()), p.Expanded())
		}

		ks := make([]vm.KeywordArgument, len(args.Keywords()))
		for i, k := range args.Keywords() {
			ks[i] = vm.NewKeywordArgument(k.Name(), c.exprToThunk(k.Value()))
{'fraction_non_alphanumeric': 0.19217622483858715, 'fraction_numerical': 0.0015191796429927839, 'mean_word_length': 3.9886363636363638, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5257905', 'n_tokens_mistral': 1030, 'n_tokens_neox': 971, 'n_words': 209}