Skip to content

Commit

Permalink
add fp
Browse files Browse the repository at this point in the history
  • Loading branch information
snowmerak committed Oct 5, 2023
1 parent 8bead09 commit c62aee8
Showing 5 changed files with 636 additions and 0 deletions.
18 changes: 18 additions & 0 deletions internal/executor/check/fp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package check

import (
"github.com/snowmerak/jetti/v2/lib/model"
"strings"
)

func HasFp(pkg *model.Package) (bool, error) {
directive := "jetti:fp"

for _, fn := range pkg.Functions {
if strings.Contains(fn.Doc, directive) {
return true, nil
}
}

return false, nil
}
12 changes: 12 additions & 0 deletions internal/executor/generate.go
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import (
"github.com/snowmerak/jetti/v2/internal/cache"
"github.com/snowmerak/jetti/v2/internal/executor/check"
"github.com/snowmerak/jetti/v2/internal/executor/generate"
"github.com/snowmerak/jetti/v2/internal/executor/generate/fp"
"github.com/snowmerak/jetti/v2/lib/parser"
"log"
"os"
@@ -145,6 +146,17 @@ func Generate(root string) error {
}
log.Printf("generate getter: %s", relativePath)
}

hasFp, err := check.HasFp(pkg)
if err != nil {
return err
}

if hasFp {
if err := fp.FunctionalProgramming(moduleName, root); err != nil {
return err
}
}
case ".json":
if err := generate.ConvertJson(path); err != nil {
return err
41 changes: 41 additions & 0 deletions internal/executor/generate/fp/functional_programming.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package fp

import (
"os"
"path/filepath"
)

func FunctionalProgramming(moduleName, root string) error {
genPath, err := InitFunctionalProgramming(root)
if err != nil {
return err
}

if err := MonadOption(genPath); err != nil {
return err
}

if err := MonadResult(genPath); err != nil {
return err
}

moduleName = moduleName + "/gen/fp"

if err := LambdaCond(moduleName, genPath); err != nil {
return err
}

if err := LambdaWhen(moduleName, genPath); err != nil {
return err
}

return nil
}

func InitFunctionalProgramming(root string) (string, error) {
functionalProgrammingPath := filepath.Join(root, "gen", "fp")
if err := os.MkdirAll(functionalProgrammingPath, os.ModePerm); err != nil {
return "", err
}
return functionalProgrammingPath, nil
}
178 changes: 178 additions & 0 deletions internal/executor/generate/fp/lambda.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package fp

import (
"github.com/snowmerak/jetti/v2/internal/executor/generate"
"github.com/snowmerak/jetti/v2/lib/generator"
"github.com/snowmerak/jetti/v2/lib/model"
"os"
"path/filepath"
)

func LambdaCond(modulePath, genPath string) error {
genPath = filepath.Join(genPath, "cond")
if err := os.MkdirAll(genPath, os.ModePerm); err != nil {
return err
}
f, err := os.Create(generate.MakeGeneratedFileName(genPath, "cond"))
if err != nil {
return err
}
defer func(f *os.File) {
if err := f.Close(); err != nil {
panic(err)
}
}(f)

pkg := &model.Package{
Name: "cond",
Imports: []model.Import{
{
Path: modulePath + "/result",
},
},
Functions: []model.Function{
{
Name: "If[T, R any]",
Params: []model.Field{
{
Name: "cond",
Type: "bool",
},
{
Name: "trueFn",
Type: "func() T",
},
{
Name: "falseFn",
Type: "func() R",
},
},
Return: []model.Field{
{
Type: "result.Result[T, R]",
},
},
Code: []string{
"if cond {",
"return result.Ok[T, R](trueFn())",
"}",
"return result.Err[T, R](falseFn())",
},
},
},
}

data, err := generator.GenerateFile(pkg)
if err != nil {
return err
}

if _, err := f.Write(data); err != nil {
return err
}

return nil
}

func LambdaWhen(modulePath, genPath string) error {
genPath = filepath.Join(genPath, "when")
if err := os.MkdirAll(genPath, os.ModePerm); err != nil {
return err
}
f, err := os.Create(generate.MakeGeneratedFileName(genPath, "when"))
if err != nil {
return err
}
defer func(f *os.File) {
if err := f.Close(); err != nil {
panic(err)
}
}(f)

pkg := &model.Package{
Name: "when",
Imports: []model.Import{
{
Path: modulePath + "/option",
},
},
Structs: []model.Struct{
{
Name: "Condition[T, R any]",
Fields: []model.Field{
{
Name: "criteria",
Type: "func (T) bool",
},
{
Name: "fn",
Type: "func (T) R",
},
},
},
},
Functions: []model.Function{
{
Name: "Cond[T, R any]",
Params: []model.Field{
{
Name: "criteria",
Type: "func (T) bool",
},
{
Name: "fn",
Type: "func (T) R",
},
},
Return: []model.Field{
{
Type: "Condition[T, R]",
},
},
Code: []string{
"return Condition[T, R]{",
"\tcriteria: criteria,",
"\tfn: fn,",
"}",
},
},
{
Name: "When[T, R any]",
Params: []model.Field{
{
Name: "criteria",
Type: "T",
},
{
Name: "cond",
Type: "...Condition[T, R]",
},
},
Return: []model.Field{
{
Type: "option.Option[R]",
},
},
Code: []string{
"for _, c := range cond {",
"\tif c.criteria(criteria) {",
"\t\treturn option.Some[R](c.fn(criteria))",
"\t}",
"}",
"return option.None[R]()",
},
},
},
}

data, err := generator.GenerateFile(pkg)
if err != nil {
return err
}

if _, err := f.Write(data); err != nil {
return err
}

return nil
}
Loading

0 comments on commit c62aee8

Please sign in to comment.