Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions apps/nyssa/app/commands/bundle.b
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def get_file_list(root_dir, main_root) {

if os.dir_exists(root_dir) {
return os.read_dir(root_dir).filter(@(f) {
return !f.starts_with('.')
return !f.starts_with('.git') and f != '.' and f != '..'
}).reduce(@(list, file) {
var full_path = os.join_paths(root_dir, file)
if os.dir_exists(full_path) {
Expand All @@ -95,10 +95,7 @@ def get_file_list(root_dir, main_root) {
}

def copy_directory(src_dir, dest_dir) {
var fls = get_file_list(src_dir).filter(@(x) {
return x != '.' and x != '..' and
!x.match('/(\\/|\\\\)[.]git\\1/')
})
var fls = get_file_list(src_dir)

for fl in fls {
var src = os.join_paths(src_dir, fl)
Expand Down
7 changes: 3 additions & 4 deletions apps/nyssa/app/index.b
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import date
import .setup

# initialize storage directory
var storage_dir = os.join_paths(setup.NYSSA_DIR, setup.STORAGE_DIR)
if !os.dir_exists(storage_dir)
os.create_dir(storage_dir)
if !os.dir_exists(setup.STORAGE_DIR)
os.create_dir(setup.STORAGE_DIR)

# ensure config file exists...
var config_file = os.join_paths(setup.NYSSA_DIR, setup.CONFIG_FILE)
Expand Down Expand Up @@ -79,7 +78,7 @@ for o in options {
}

def success(msg, info) {
log.info(cmsg)
log.info(msg)

if info {
log.info(info)
Expand Down
4 changes: 4 additions & 0 deletions libs/args.b
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,10 @@ class Parser < _Optionable {
if i < cli_args.length() - 1 {
i++
var value = cli_args[i]
if command.type == LIST {
value = [value]
}

var v = _get_real_value(command, value)

if command.type != CHOICE or !command.choices or command.choices.contains(value) {
Expand Down
5 changes: 4 additions & 1 deletion libs/ast/expr.b
Original file line number Diff line number Diff line change
Expand Up @@ -247,16 +247,19 @@ class SetExpr < Expr {
class IndexExpr < Expr {

/**
* @param {Expr|any|nil} expr
* @param {Expr|any|nil} args
* @constructor
*/
IndexExpr(args) {
IndexExpr(expr, args) {
self.expr = expr
self.args = args
}

@to_json() {
return {
type: 'IndexExpr',
expr: self.expr,
args: self.args,
}
}
Expand Down
15 changes: 7 additions & 8 deletions libs/ast/parser.b
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ class Parser {

self._ignore_newline()
self._consume(TokenType.RBRACKET, "']' expected at end of indexer")
return IndexExpr(args)
return IndexExpr(callee, args)
}

/**
Expand Down Expand Up @@ -734,7 +734,7 @@ class Parser {
*/
_using() {
var expr = self._expression()
var cases = {}
var cases = []
var default_case

self._consume(TokenType.LBRACE, "'{' expected after using expression")
Expand All @@ -749,17 +749,16 @@ class Parser {

if [TokenType.DOC, TokenType.COMMENT, TokenType.NEWLINE].contains(self._previous().type) {}
else if self._previous().type == TokenType.WHEN {
var tmp_cases = []
var conditions = []

do {
self._ignore_newline()

tmp_cases.append(self._expression())
conditions.append(self._expression())
} while self._match(TokenType.COMMA)

var stmt = self._statement()
cases.append(CaseStmt(conditions, stmt))

for tmp in tmp_cases {
cases[tmp] = stmt
}
} else {
state = 1
default_case = self._statement()
Expand Down
10 changes: 5 additions & 5 deletions libs/ast/scanner.b
Original file line number Diff line number Diff line change
Expand Up @@ -263,14 +263,14 @@ class Scanner {
*/
_string(c) {
while self._peek() != c and !self._is_at_end() {
if self._peek() == '$' and self._next() == '{' and
self._previous() != '\\' { # interpolation started
# interpolation expression
if self._peek() == '$' and self._next() == '{' and self._previous() != '\\' {
self._current++
self._current++

if self._interpolating.length() < self._max_interpolation_nest {
self._interpolating.append(c)
self._current++
self._add_token(TokenType.INTERPOLATION)
self._current++
return
}

Expand All @@ -287,7 +287,7 @@ class Scanner {
raise Exception('unterminated string on line ${self._line}')

self._match(c)
self._add_token(TokenType.LITERAL, self.source[self._start + 1, self._current - 1])
self._add_token(TokenType.LITERAL, self.source[self._start, self._current])
}

/**
Expand Down
26 changes: 26 additions & 0 deletions libs/ast/stmt.b
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,32 @@ class UsingStmt < Stmt {
}
}

/**
* Case Stmt representation.
*
* @serializable
*/
class CaseStmt < Stmt {

/**
* @param {Stmt|any|nil} conditions
* @param {Stmt|any|nil} statement
* @constructor
*/
CaseStmt(conditions, statement) {
self.conditions = conditions
self.statement = statement
}

@to_json() {
return {
type: 'CaseStmt',
conditions: self.conditions,
statement: self.statement,
}
}
}

/**
* Import Stmt representation.
*
Expand Down
12 changes: 8 additions & 4 deletions libs/http/server.b
Original file line number Diff line number Diff line change
Expand Up @@ -497,10 +497,14 @@ class HttpServer {
client.close()

if e {
# call the error listeners.
self._error_listeners.each(@(fn) {
fn(e, client)
})
if self._error_listeners.length() == 0 {
raise e
} else {
# call the error listeners.
self._error_listeners.each(@(fn) {
fn(e, client)
})
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion libs/reflect.b
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ def set_ptr(pointer, value) {
}

/**
* Returns a the address of the pointer to the value in memory.
* Returns the address of the pointer to the value in memory.
*
* @param any value
* @returns ptr
Expand Down
34 changes: 34 additions & 0 deletions libs/thread.b
Original file line number Diff line number Diff line change
Expand Up @@ -561,3 +561,37 @@ def start(delegate, args) {
thread.start_from_list(args)
return thread
}

/**
* Awaits all threads in the given list and returns when the last
* element exits.
*
* @param list threads
*/
def await_list(threads) {
if !is_list(threads)
raise ArgumentError('list of threads expected')

for thread in threads {
if !instance_of(thread, Thread)
raise ValueError('list of threads expected')

thread.await()
}
}

/**
* Awaits all threads passed as an argument. This function is the
* same as [[thread.await_list()]], but allows passing the items as
* known arguments.
*
* @param [[thread.Thread]]... threads
*/
def await_all(...) {
for thread in __args__ {
if !instance_of(thread, Thread)
raise ValueError('list of threads expected')

thread.await()
}
}
36 changes: 33 additions & 3 deletions packages/clib/clib.c
Original file line number Diff line number Diff line change
Expand Up @@ -644,9 +644,9 @@ b_value get_blade_value(b_vm *vm, int type, size_t size, void *data, size_t *rea
}

DECLARE_MODULE_METHOD(clib_get) {
ENFORCE_ARG_COUNT(new, 2);
ENFORCE_ARG_TYPE(new, 0, IS_PTR);
ENFORCE_ARG_TYPES(new, 1, IS_BYTES, IS_PTR);
ENFORCE_ARG_COUNT(get, 2);
ENFORCE_ARG_TYPE(get, 0, IS_PTR);
ENFORCE_ARG_TYPES(get, 1, IS_BYTES, IS_PTR);

b_ffi_type *type = (b_ffi_type *)AS_PTR(args[0])->pointer;
if(type->as_ffi->elements == NULL) {
Expand Down Expand Up @@ -687,6 +687,35 @@ DECLARE_MODULE_METHOD(clib_get) {
RETURN_OBJ(list);
}

DECLARE_MODULE_METHOD(clib_get_value) {
ENFORCE_ARG_COUNT(get_value, 2);
ENFORCE_ARG_TYPE(get_value, 0, IS_PTR);
ENFORCE_ARG_TYPES(get_value, 1, IS_BYTES, IS_PTR);

b_ffi_type *type = (b_ffi_type *)AS_PTR(args[0])->pointer;
if(type->as_ffi->elements != NULL) {
RETURN_ARGUMENT_ERROR("get_value can only be used on non-derived types such as struct, union and arrays.");
}

unsigned char *data;
if(IS_PTR(args[1])) {
data = (unsigned char *)AS_PTR(args[1])->pointer;
} else {
data = AS_BYTES(args[1])->bytes.bytes;
}

b_obj_list *list = (b_obj_list *)GC(new_list(vm));

size_t read_len = 0;
RETURN_VALUE(get_blade_value(
vm,
type->as_int,
type->as_ffi->size,
data,
&read_len
));
}

DECLARE_MODULE_METHOD(clib_define) {
ENFORCE_ARG_COUNT(define, 4);
ENFORCE_ARG_TYPE(define, 0, IS_PTR);
Expand Down Expand Up @@ -882,6 +911,7 @@ CREATE_MODULE_LOADER(clib) {
static b_func_reg module_functions[] = {
{"new", true, GET_MODULE_METHOD(clib_new)},
{"get", true, GET_MODULE_METHOD(clib_get)},
{"get_value", true, GET_MODULE_METHOD(clib_get_value)},
{"load", true, GET_MODULE_METHOD(clib_load_library)},
{"function", true, GET_MODULE_METHOD(clib_get_function)},
{"close", true, GET_MODULE_METHOD(clib_close_library)},
Expand Down
40 changes: 34 additions & 6 deletions packages/clib/clib/index.b
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,20 @@ class Clib {
load(name) {
if !is_string(name)
raise TypeError('string expected in argument 1 (name)')
if !name.ends_with(_EXT) and os.platform != 'linux'
name += _EXT


var library_name = !name.ends_with(_EXT) and os.platform != 'linux' ?
name + _EXT : name

if self._ptr
self.close()
self._ptr = _clib.load(name)

catch {
self._ptr = _clib.load(name)
} as error

if error {
self._ptr = _clib.load(library_name)
}
}

/**
Expand Down Expand Up @@ -205,7 +213,7 @@ def new(type, ...) {
}

/**
* Returns the data contained in a C type _type_ encoded in the data.
* Returns the data contained in a C derived type _type_ encoded in the data.
* The data should either be an output of `clib.new()` or a call to a
* function returning one of struct, union or array.
*
Expand All @@ -220,12 +228,32 @@ def new(type, ...) {
def get(type, data) {
# Ensure a valid and non void clib pointer.
if !(reflect.is_ptr(type) and to_string(type).match('/clib/')) and type != void
raise ValueError('invalid type for new')
raise ValueError('invalid type for get')
if is_string(data) data = data.to_bytes()

return _clib.get(type, data)
}

/**
* Returns the data contained in a C non-derived type _type_ encoded in the data.
* The data should NOT either be an output of `clib.new()` or a call to any
* function returning one of struct, union or array.
*
* This is the opposite of [[clib.get]]
*
* @param clib_type type
* @param string|bytes data
* @returns any
*/
def get_value(type, data) {
# Ensure a valid and non void clib pointer.
if !(reflect.is_ptr(type) and to_string(type).match('/clib/')) and type != void
raise ValueError('invalid type for get_value')
if is_string(data) data = data.to_bytes()

return _clib.get_value(type, data)
}

/**
* get_ptr_index(pointer: ptr, type: clib_type, index: number)
*
Expand Down
Loading
Loading