<commit_before>package eval

import (
	"fmt"

	"github.com/cirbo-lang/cirbo/cty"
	"github.com/cirbo-lang/cirbo/source"
)

type Stmt struct {
	s stmtImpl
}

// NilStmt is an invalid expression that serves as the zero value of Stmt.
//
// NilStmt indicates the absense of an expression and is not itself a valid
// expression. Any methods called on it will panic.
var NilStmt Stmt

type stmtImpl interface {
	definedSymbol() *Symbol
	requiredSymbols(scope *Scope) SymbolSet
	execute(exec *StmtBlockExecute, result *StmtBlockResult) source.Diags
	sourceRange() source.Range
}

type assignStmt struct {
	sym  *Symbol
	expr Expr
	rng
}

func AssignStmt(sym *Symbol, expr Expr, rng source.Range) Stmt {
	return Stmt{&assignStmt{
		sym:  sym,
		expr: expr,
		rng:  srcRange(rng),
	}}
}

func (s *assignStmt) definedSymbol() *Symbol {
	return s.sym
}

func (s *assignStmt) requiredSymbols(scope *Scope) SymbolSet {
	return s.expr.RequiredSymbols(scope)
}

func (s *assignStmt) execute(exec *StmtBlockExecute, result *StmtBlockResult) source.Diags {
	_, diags := exec.Context.Define(s.sym, s.expr)
	return diags
}

type importStmt struct {
	ppath string
	sym   *Symbol
	rng
	nonExprStmt
}

func ImportStmt(ppath string, sym *Symbol, rng source.Range) Stmt {
	return Stmt{&importStmt{
		ppath: ppath,
		sym:   sym,
		rng:   srcRange(rng),
	}}
}

func (s *importStmt) definedSymbol() *Symbol {
	return s.sym
}

func (s *importStmt) execute(exec *StmtBlockExecute, result *StmtBlockResult) source.Diags {
	var diags source.Diags
	val, defined := exec.Modules[s.ppath]
	if !defined {
		val = cty.PlaceholderVal
		diags = append(diags, source.Diag{
			Level:   source.Error,
			Summary: "Module not loaded",
			Detail:  fmt.Sprintf("The module %q has not yet been loaded. This is a bug in Cirbo that should be reported!", s.ppath),
			Ranges:  s.sourceRange().List(),
		})
	}
	exec.Context.DefineLiteral(s.sym, val)
	return diags
}

type attrStmt struct {
	sym *Symbol

	// Either defValue or valueType must be set, and not both
	defValue, valueType Expr

	rng
}

func AttrStmt(sym *Symbol, valueType Expr, rng source.Range) Stmt {
	return Stmt{&attrStmt{
		sym:       sym,
		valueType: valueType,
		rng:       srcRange(rng),
	}}
}

func AttrStmtDefault(sym *Symbol, defValue Expr, rng source.Range) Stmt {
	return Stmt{&attrStmt{
		sym:      sym,
		defValue: defValue,
		rng:      srcRange(rng),
	}}
}

func (s *attrStmt) definedSymbol() *Symbol {
	return s.sym
}
<commit_msg>eval: ExportStmt<commit_after>package eval

import (
	"fmt"

	"github.com/cirbo-lang/cirbo/cty"
	"github.com/cirbo-lang/cirbo/source"
)

type Stmt struct {
	s stmtImpl
}

// NilStmt is an invalid expression that serves as the zero value of Stmt.
//
// NilStmt indicates the absense of an expression and is not itself a valid
// expression. Any methods called on it will panic.
var NilStmt Stmt

type stmtImpl interface {
	definedSymbol() *Symbol
	requiredSymbols(scope *Scope) SymbolSet
	execute(exec *StmtBlockExecute, result *StmtBlockResult) source.Diags
	sourceRange() source.Range
}

type assignStmt struct {
	sym  *Symbol
	expr Expr
	rng
}

func AssignStmt(sym *Symbol, expr Expr, rng source.Range) Stmt {
	return Stmt{&assignStmt{
		sym:  sym,
		expr: expr,
		rng:  srcRange(rng),
	}}
}

func (s *assignStmt) definedSymbol() *Symbol {
	return s.sym
}

func (s *assignStmt) requiredSymbols(scope *Scope) SymbolSet {
	return s.expr.RequiredSymbols(scope)
}

func (s *assignStmt) execute(exec *StmtBlockExecute, result *StmtBlockResult) source.Diags {
	_, diags := exec.Context.Define(s.sym, s.expr)
	return diags
}

type importStmt struct {
	ppath string
	sym   *Symbol
	rng
	nonExprStmt
}

func ImportStmt(ppath string, sym *Symbol, rng source.Range) Stmt {
	return Stmt{&importStmt{
		ppath: ppath,
		sym:   sym,
		rng:   srcRange(rng),
	}}
}

func (s *importStmt) definedSymbol() *Symbol {
	return s.sym
}

func (s *importStmt) execute(exec *StmtBlockExecute, result *StmtBlockResult) source.Diags {
	var diags source.Diags
	val, defined := exec.Modules[s.ppath]
	if !defined {
		val = cty.PlaceholderVal
		diags = append(diags, source.Diag{
			Level:   source.Error,
			Summary: "Module not loaded",
			Detail:  fmt.Sprintf("The module %q has not yet been loaded. This is a bug in Cirbo that should be reported!", s.ppath),
			Ranges:  s.sourceRange().List(),
		})
	}
	exec.Context.DefineLiteral(s.sym, val)
	return diags
}

type exportStmt struct {
	value Expr
	rng
	nonDefStmt
}

func ExportStmt(value Expr, rng source.Range) Stmt {
	return Stmt{&exportStmt{
		value: value,
		rng:   srcRange(rng),
	}}
}

func (s *exportStmt) execute(exec *StmtBlockExecute, result *StmtBlockResult) source.Diags {
	val, diags := s.value.Value(exec.Context)
	if result.ExportValue != cty.NilValue {
		diags = append(diags, source.Diag{
			Level:   source.Error,
			Summary: "Duplicate export statements",
			Detail:  "Only one export statement is permitted per module.",
			Ranges:  s.sourceRange().List(),
		})
		return diags
	}
	result.ExportValue = val
	return diags
}

func (s *exportStmt) requiredSymbols(scope *Scope) SymbolSet {
	return s.value.RequiredSymbols(scope)
}

type attrStmt struct {
	sym *Symbol

	// Either defValue or valueType must be set, and not both
	defValue, valueType Expr

	rng
}

func AttrStmt(sym *Symbol, valueType Expr, rng source.Range) Stmt {
	return Stmt{&attrStmt{
		sym:       sym,
		valueType: valueType,
		rng:       srcRange(rng),
	}}
}

func AttrStmtDefault(sym *Symbol, defValue Expr, rng source.Range) Stmt {
	return Stmt{&attrStmt{
		sym:      sym,
		defValue: defValue,
		rng:      srcRange(rng),
	}}
}

func (s *attrStmt) definedSymbol() *Symbol {
	return s.sym
}

{'fraction_non_alphanumeric': 0.11115031757233593, 'fraction_numerical': 0.0, 'mean_word_length': 3.985927880386983, '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': '5163034', 'n_tokens_mistral': 2104, 'n_tokens_neox': 2091, 'n_words': 584}