Skip to content

Commit

Permalink
支持 built-in mods
Browse files Browse the repository at this point in the history
  • Loading branch information
lollipopkit committed Oct 27, 2022
1 parent 558909f commit 3a0efa1
Show file tree
Hide file tree
Showing 12 changed files with 203 additions and 16 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#### 速览
```js
// http发送请求示例
shy resp, err = http.post(
resp, err := http.post(
'http://httpbin.org/post', // URL
{'accept': 'application/json'}, // Headers
'{"foo": "bar"}' // Body
Expand Down
2 changes: 1 addition & 1 deletion consts/lang.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package consts

var (
const (
VERSION = `0.1.6`
SIGNATURE = `LANG_LK`
)
6 changes: 5 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@ import (
"flag"
"strings"

"git.lolli.tech/lollipopkit/lk/mods"
"git.lolli.tech/lollipopkit/lk/state"
)

var (
args = []string{}
)

func init() {
go mods.InitMods()
}

func main() {
flag.Parse()

args = flag.Args()
if len(args) == 0 {
repl()
Expand Down
18 changes: 18 additions & 0 deletions mods/files/table.lk
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class table {}

fn table.contains(tb, item) {
for _, v in tb {
if v == item {
rt true
}
}
rt false
}

fn table.len(tb) {
i := 0
for _, _ in tb {
i += 1
}
rt i
}
4 changes: 4 additions & 0 deletions mods/index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"vm": "0.1.6",
"version": 2210261834
}
84 changes: 84 additions & 0 deletions mods/mod.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package mods

import (
"embed"
"io/ioutil"
"os"
"path"

"git.lolli.tech/lollipopkit/lk/consts"
"git.lolli.tech/lollipopkit/lk/term"
"git.lolli.tech/lollipopkit/lk/utils"
"github.com/tidwall/gjson"
)

var (
//go:embed index.json files
ModFiles embed.FS
LkEnv = os.Getenv("LK_PATH")

indexFilePath = path.Join(LkEnv, "index.json")
builtInIndexPath = "index.json"
builtInFilesPath = "files"
)

func init() {
if LkEnv == "" {
term.Warn("env LK_PATH not set. \nCan't use built-in modules.")
}
}

func InitMods() {
if LkEnv == "" {
return
}
if utils.Exist(indexFilePath) {
indexBytes, err := ioutil.ReadFile(indexFilePath)
if err != nil {
term.Error("can't read index.json: " + err.Error())
}
index := gjson.ParseBytes(indexBytes).Map()
sameVM := index["vm"].String() == consts.VERSION
version := index["version"].Int()
bulitInIndexBytes, err := ModFiles.ReadFile(builtInIndexPath)
if err != nil {
term.Error("can't read built-in index.json: " + err.Error())
}
builtInIndex := gjson.ParseBytes(bulitInIndexBytes).Map()
builtInVersion := builtInIndex["version"].Int()
if version >= builtInVersion && sameVM {
return
}
}
extract()
}

func extract() {
term.Info("Extracting built-in modules...")
index, err := ModFiles.ReadFile(builtInIndexPath)
if err != nil {
term.Error("can't read index.json: " + err.Error())
}
err = os.WriteFile(indexFilePath, index, 0644)
if err != nil {
term.Error("can't write index.json: " + err.Error())
}
files, err := ModFiles.ReadDir(builtInFilesPath)
if err != nil {
term.Error("can't read files: " + err.Error())
}

for idx := range files {
if files[idx].IsDir() {
continue
}
data, err := ModFiles.ReadFile(path.Join(builtInFilesPath, files[idx].Name()))
if err != nil {
term.Error("can't read file: " + err.Error())
}
err = os.WriteFile(path.Join(LkEnv, files[idx].Name()), data, 0644)
if err != nil {
term.Error("can't write file: " + err.Error())
}
}
}
14 changes: 4 additions & 10 deletions state/api_call.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package state
import (
"fmt"
"io/ioutil"
"os"
"strings"

. "git.lolli.tech/lollipopkit/lk/api"
Expand All @@ -19,7 +18,7 @@ func Compile(source string) *binchunk.Prototype {
source = source[1:]
}

if !exist(source) {
if !utils.Exist(source) {
term.Error("[compile] file not found: " + source)
}

Expand All @@ -41,21 +40,16 @@ func Compile(source string) *binchunk.Prototype {
return bin
}

func exist(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}

func loadlk(source string) *binchunk.Prototype {
lkc := source + "c"
if exist(lkc) {
if utils.Exist(lkc) {
return loadlkc(lkc)
}
return Compile(source)
}

func loadlkc(source string) *binchunk.Prototype {
if !exist(source) {
if !utils.Exist(source) {
term.Error("[run] file not found: " + source)
}

Expand All @@ -66,7 +60,7 @@ func loadlkc(source string) *binchunk.Prototype {

lkPath := source[:len(source)-1]
var lkData []byte
lkExist := exist(lkPath)
lkExist := utils.Exist(lkPath)
if lkExist {
lkData, err = ioutil.ReadFile(lkPath)
if err != nil {
Expand Down
5 changes: 4 additions & 1 deletion stdlib/lib_package.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package stdlib

import (
"os"
"path"
"strings"

. "git.lolli.tech/lollipopkit/lk/api"
"git.lolli.tech/lollipopkit/lk/mods"
)

/* key, in the registry, for table of loaded modules */
Expand Down Expand Up @@ -39,7 +41,8 @@ func OpenPackageLib(ls LkState) int {
ls.NewLib(pkgFuncs) /* create 'package' table */
createSearchersTable(ls)
/* set paths */
ls.PushString("./?.lk;./?/init.lk")
lkEnv := mods.LkEnv
ls.PushString("./?.lk;./?/init.lk;" + path.Join(lkEnv, "?.lk") + ";" + path.Join(lkEnv, "?/init.lk"))
ls.SetField(-2, "path")
/* store config information */
ls.PushString(LUA_DIRSEP + "\n" + LUA_PATH_SEP + "\n" +
Expand Down
2 changes: 1 addition & 1 deletion stdlib/lib_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var strLib = map[string]GoFunction{
"byte": strByte,
"char": strChar,
"split": strSplit,
"join": strJoin,
"join": strJoin,
}

func OpenStringLib(ls LkState) int {
Expand Down
6 changes: 6 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@ package utils
import (
"crypto/md5"
"fmt"
"os"
)

func Md5(data []byte) string {
return fmt.Sprintf("%x", md5.Sum(data))
}

func Exist(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}
74 changes: 74 additions & 0 deletions utils/zip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package utils

import (
"archive/zip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)

func Unzip(src, dest string) error {
r, err := zip.OpenReader(src)
if err != nil {
return err
}
defer func() {
if err := r.Close(); err != nil {
panic(err)
}
}()

os.MkdirAll(dest, 0755)

// Closure to address file descriptors issue with all the deferred .Close() methods
extractAndWriteFile := func(f *zip.File) error {
rc, err := f.Open()
if err != nil {
return err
}
defer func() {
if err := rc.Close(); err != nil {
panic(err)
}
}()

path := filepath.Join(dest, f.Name)

// Check for ZipSlip (Directory traversal)
if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) {
return fmt.Errorf("illegal file path: %s", path)
}

if f.FileInfo().IsDir() {
os.MkdirAll(path, f.Mode())
} else {
os.MkdirAll(filepath.Dir(path), f.Mode())
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return err
}
defer func() {
if err := f.Close(); err != nil {
panic(err)
}
}()

_, err = io.Copy(f, rc)
if err != nil {
return err
}
}
return nil
}

for _, f := range r.File {
err := extractAndWriteFile(f)
if err != nil {
return err
}
}

return nil
}
2 changes: 1 addition & 1 deletion vm/instruction.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,6 @@ func (self Instruction) Execute(vm api.LuaVM) {
if action != nil {
action(self, vm)
} else {
panic("No instruction: "+self.OpName())
panic("No instruction: " + self.OpName())
}
}

0 comments on commit 3a0efa1

Please sign in to comment.