Skip to content

Commit

Permalink
feat!: keywords alias of block braces
Browse files Browse the repository at this point in the history
  • Loading branch information
moisespsena committed Sep 28, 2023
1 parent 292f1e8 commit d9369da
Show file tree
Hide file tree
Showing 19 changed files with 536 additions and 253 deletions.
59 changes: 59 additions & 0 deletions builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ const (
BuiltinKeyValue
BuiltinKeyValueArray
BuiltinBuffer

BuiltinVMPushWriter
BuiltinVMPopWriter

BuiltinDiscardWriter
)

// BuiltinsMap is list of builtin types, exported for REPL.
Expand Down Expand Up @@ -158,6 +163,10 @@ var BuiltinsMap = map[string]BuiltinType{
"items": BuiltinItems,
"keyValue": BuiltinKeyValue,
"keyValueArray": BuiltinKeyValueArray,

"vmPushWriter": BuiltinVMPushWriter,
"vmPopWriter": BuiltinVMPopWriter,
"DISCARD_WRITER": BuiltinDiscardWriter,
}

// BuiltinObjects is list of builtins, exported for REPL.
Expand Down Expand Up @@ -364,6 +373,15 @@ var BuiltinObjects = [...]Object{
Value: builtinStdIO,
},

BuiltinVMPushWriter: &BuiltinFunction{
Name: "vmPushWriter",
Value: builtinVMPushWriterFunc,
},
BuiltinVMPopWriter: &BuiltinFunction{
Name: "vmPopWriter",
Value: builtinVMPopWriterFunc,
},

BuiltinWrongNumArgumentsError: ErrWrongNumArguments,
BuiltinInvalidOperatorError: ErrInvalidOperator,
BuiltinIndexOutOfBoundsError: ErrIndexOutOfBounds,
Expand All @@ -374,6 +392,8 @@ var BuiltinObjects = [...]Object{
BuiltinNotImplementedError: ErrNotImplemented,
BuiltinZeroDivisionError: ErrZeroDivision,
BuiltinTypeError: ErrType,

BuiltinDiscardWriter: DiscardWriter,
}

func builtinMakeArrayFunc(n int, arg Object) (Object, error) {
Expand Down Expand Up @@ -797,6 +817,10 @@ func builtinWriteFunc(c Call) (ret Object, err error) {
n int
)

if l := len(c.vm.writers); l > 0 {
w = c.vm.writers[l-1]
}

if err = c.Args.CheckMinLen(1); err != nil {
return
}
Expand Down Expand Up @@ -1212,3 +1236,38 @@ func builtinStdIO(c Call) (ret Object, err error) {
}
return
}

func builtinVMPushWriterFunc(c Call) (ret Object, err error) {
if c.Args.Len() == 0 {
buf := &Buffer{}
c.vm.PushWriter(buf)
return buf, nil
}

if err := c.Args.CheckMaxLen(1); err != nil {
return nil, err
}

arg := c.Args.Get(0)
if arg == Nil {
arg = DiscardWriter
}
if w, ok := arg.(Writer); ok {
c.vm.PushWriter(w)
return w, nil
}

return nil, NewArgumentTypeError(
"1st",
"writer",
arg.TypeName(),
)
}

func builtinVMPopWriterFunc(c Call) (ret Object, err error) {
if len(c.vm.writers) == 0 {
return nil, ErrUnbuffered
}
c.vm.PopWriter()
return Nil, nil
}
8 changes: 4 additions & 4 deletions cmd/gad/internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ func TestREPL(t *testing.T) {
t.Run("builtins", func(t *testing.T) {
require.NoError(t, r.execute(".builtins"))
testHasPrefix(t, string(cw.consume()),
"IndexOutOfBoundsError \tBuiltin Error\n")
"DISCARD_WRITER \tBuiltin\n")
})
t.Run("keywords", func(t *testing.T) {
require.NoError(t, r.execute(".keywords"))
testHasPrefix(t, string(cw.consume()),
"break\ncontinue\nelse\nfor\nfunc\nif\nreturn\ntrue\nfalse\nin\n"+
"nil\nimport\nparam\nglobal\nvar\nconst\ntry\ncatch\n"+
"finally\nthrow\n",
"then\ndo\nbegin\nend\nbreak\ncontinue\nelse\nfor\nfunc\nif\nreturn\ntrue\nfalse\nin\nnil\n"+
"import\nparam\nglobal\nvar\nconst\ntry\ncatch\nfinally\nthrow\n__callee__\n__named_args__\n__args__\n"+
"STDIN\nSTDOUT\nSTDERR\n",
)
})
t.Run("unresolved reference", func(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,8 @@ func (c *Compiler) Compile(node parser.Node) error {
return c.compileImportExpr(node)
case *parser.CondExpr:
return c.compileCondExpr(node)
case *parser.CodeStmt:
return c.compileStmts(node.Stmts...)
case *parser.TextStmt:
return c.Compile(&parser.StringLit{Value: node.Literal})
case *parser.EmptyStmt:
case *parser.ConfigStmt:
if node.Options.WriteFunc != nil {
Expand Down
6 changes: 2 additions & 4 deletions compiler_nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -715,10 +715,8 @@ func (c *Compiler) compileBlockStmt(node *parser.BlockStmt) error {
}

c.symbolTable = c.symbolTable.Fork(true)
for _, stmt := range node.Stmts {
if err := c.Compile(stmt); err != nil {
return err
}
if err := c.compileStmts(node.Stmts...); err != nil {
return err
}

c.symbolTable = c.symbolTable.Parent(false)
Expand Down
55 changes: 53 additions & 2 deletions compiler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ func TestCompiler_CompileIfNull(t *testing.T) {
}

func TestCompiler_Mixed(t *testing.T) {
expectCompileMixed(t, `# gad: writer=myfn; #{<>var myfn} a`, bytecode(
expectCompileMixed(t, `# gad: writer=myfn; #{- var myfn -} a`, bytecode(
Array{String("a")},
compFunc(concatInsts(
makeInst(OpNull),
Expand Down Expand Up @@ -234,7 +234,7 @@ func TestCompiler_Mixed(t *testing.T) {
), withLocals(1)),
))

expectCompile(t, `# gad: mixed, writer=myfn; #{<>var myfn} a`, bytecode(
expectCompile(t, `# gad: mixed, writer=myfn; #{- var myfn -} a`, bytecode(
Array{String("a")},
compFunc(concatInsts(
makeInst(OpNull),
Expand All @@ -245,6 +245,57 @@ func TestCompiler_Mixed(t *testing.T) {
makeInst(OpReturn, 0),
), withLocals(1)),
))

expectCompile(t, `# gad: mixed; #{- a := begin} a #{end}`, bytecode(
Array{String(" a ")},
compFunc(concatInsts(
makeInst(OpConstant, 0),
makeInst(OpDefineLocal, 0),
makeInst(OpReturn, 0),
), withLocals(1)),
))

expectCompile(t, `# gad: mixed; #{- a := begin -} a #{- end}`, bytecode(
Array{String("a")},
compFunc(concatInsts(
makeInst(OpConstant, 0),
makeInst(OpDefineLocal, 0),
makeInst(OpReturn, 0),
), withLocals(1)),
))

expectCompile(t, `# gad: mixed; #{- a := begin -} a #{- end; return a}`, bytecode(
Array{String("a")},
compFunc(concatInsts(
makeInst(OpConstant, 0),
makeInst(OpDefineLocal, 0),
makeInst(OpGetLocal, 0),
makeInst(OpReturn, 1),
), withLocals(1)),
))

expectCompile(t, `# gad: mixed; #{- a := begin -} a #{- end}#{return a}`, bytecode(
Array{String("a")},
compFunc(concatInsts(
makeInst(OpConstant, 0),
makeInst(OpDefineLocal, 0),
makeInst(OpGetLocal, 0),
makeInst(OpReturn, 1),
), withLocals(1)),
))

expectCompile(t, `# gad: mixed; #{- a := begin -} a #{- end} b #{return a}`, bytecode(
Array{String("a"), String(" b ")},
compFunc(concatInsts(
makeInst(OpConstant, 0),
makeInst(OpDefineLocal, 0),
makeInst(OpGetBuiltin, int(BuiltinWrite)),
makeInst(OpConstant, 1),
makeInst(OpCall, 1, 0),
makeInst(OpGetLocal, 0),
makeInst(OpReturn, 1),
), withLocals(1)),
))
}

func TestCompiler_Compile(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ var (

// ErrType represents a type error.
ErrType = &Error{Name: "TypeError"}

// ErrUnbuffered represents a vm umbuffered type error.
ErrUnbuffered = &Error{Name: "UnbufferedError"}
)

// NewOperandTypeError creates a new Error from ErrType.
Expand Down
5 changes: 5 additions & 0 deletions objects_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,8 @@ type Reader interface {
io.Reader
GoReader() io.Reader
}

type ReadWriter interface {
Writer
Reader
}
16 changes: 15 additions & 1 deletion objects_io.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,26 @@ type ToWriter interface {

type writer struct {
io.Writer
name string
}

func NewWriter(w io.Writer) Writer {
return &writer{Writer: w}
}

func NewNamedWriter(w io.Writer, name string) Writer {
return &writer{Writer: w, name: name}
}

func (w *writer) Name() string {
return w.name
}

func (w *writer) TypeName() string {
return "writer"
if w.name == "" {
return "writer"
}
return "writer:" + w.name
}

func (w *writer) String() string {
Expand Down Expand Up @@ -182,3 +194,5 @@ func (o *Buffer) CallName(name string, c Call) (Object, error) {
func (o *Buffer) ToBytes() (Bytes, error) {
return o.Bytes(), nil
}

var DiscardWriter = NewNamedWriter(io.Discard, "discard")
1 change: 1 addition & 0 deletions opcodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const (
OpCallee
OpArgs
OpNamedArgs
OpTextWriter
)

// OpcodeNames are string representation of opcodes.
Expand Down
5 changes: 3 additions & 2 deletions optimizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ func canOptimizeInsts(constants []Object, insts []byte) bool {
OpTrue: true, OpFalse: true, OpJumpNull: true, OpJumpNotNull: true,
OpCallee: true, OpArgs: true, OpNamedArgs: true,
OpStdIn: true, OpStdOut: true, OpStdErr: true,
OpTextWriter: true,
}

allowedBuiltins := [...]bool{
Expand All @@ -151,8 +152,8 @@ func canOptimizeInsts(constants []Object, insts []byte) bool {
BuiltinIsArray: true, BuiltinIsNil: true, BuiltinIsIterable: true,
BuiltinDecimal: true, BuiltinItems: true, BuiltinValues: true,
BuiltinKeys: true, BuiltinKeyValue: true, BuiltinKeyValueArray: true,
BuiltinBuffer: true,
^byte(0): false,
BuiltinBuffer: true, BuiltinVMPushWriter: true, BuiltinVMPopWriter: true,
^byte(0): false,
}

canOptimize := true
Expand Down
Loading

0 comments on commit d9369da

Please sign in to comment.