mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-02-11 15:16:41 +08:00
fixed: iterator (internal) variables popped twise.
printing stack trace implemented
This commit is contained in:
parent
9c77ff5a6c
commit
c3041c74a9
@ -10,7 +10,13 @@
|
|||||||
|
|
||||||
void errorPrint(PKVM* vm, PKErrorType type, const char* file, int line,
|
void errorPrint(PKVM* vm, PKErrorType type, const char* file, int line,
|
||||||
const char* message) {
|
const char* message) {
|
||||||
|
if (type == PK_ERROR_COMPILE) {
|
||||||
fprintf(stderr, "Error: %s\n\tat %s:%i\n", message, file, line);
|
fprintf(stderr, "Error: %s\n\tat %s:%i\n", message, file, line);
|
||||||
|
} else if (type == PK_ERROR_RUNTIME) {
|
||||||
|
fprintf(stderr, "Error: %s\n", message);
|
||||||
|
} else if (type == PK_ERROR_STACKTRACE) {
|
||||||
|
fprintf(stderr, " [%s:%i] %s()\n", file, line, message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeFunction(PKVM* vm, const char* text) {
|
void writeFunction(PKVM* vm, const char* text) {
|
||||||
|
39
docs/static/try_now.js
vendored
39
docs/static/try_now.js
vendored
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2021 Thakee Nathees
|
|
||||||
* Licensed under: MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
const _initial_snippet = `\
|
|
||||||
# A recursive fibonacci function.
|
|
||||||
def fib(n)
|
|
||||||
if n < 2 then return n end
|
|
||||||
return fib(n-1) + fib(n-2)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Print all fibonacci from 0 to 5 exclusive.
|
|
||||||
for i in 0..5
|
|
||||||
print(fib(i))
|
|
||||||
end
|
|
||||||
`
|
|
||||||
|
|
||||||
var highlight_fn = function(editor) {
|
|
||||||
// highlight.js does not trim old tags,
|
|
||||||
// let's do it by this hack.
|
|
||||||
editor.textContent = editor.textContent;
|
|
||||||
editor.innerHTML = Prism.highlight(editor.textContent, Prism.languages.ruby, 'ruby');
|
|
||||||
}
|
|
||||||
|
|
||||||
var runSource;
|
|
||||||
window.onload = function() { // called after index.html is loaded -> Module is defined.
|
|
||||||
runSource = Module.cwrap('runSource', 'number', ['string']);
|
|
||||||
document.getElementById("run-button").onclick = function() {
|
|
||||||
document.getElementById('output').innerText = '';
|
|
||||||
const source = document.querySelector('.editor').textContent;
|
|
||||||
runSource(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
let editor = document.querySelector('.editor')
|
|
||||||
editor.textContent = _initial_snippet;
|
|
||||||
highlight_fn(editor);
|
|
||||||
}
|
|
||||||
|
|
@ -10,9 +10,19 @@
|
|||||||
mergeInto(LibraryManager.library, {
|
mergeInto(LibraryManager.library, {
|
||||||
/** js_func_name : function() {...} */
|
/** js_func_name : function() {...} */
|
||||||
|
|
||||||
js_errorPrint : function(message, line) {
|
js_errorPrint : function(type, line, message) {
|
||||||
|
var err_text = ''
|
||||||
|
const msg = AsciiToString(message);
|
||||||
|
if (type == 0 /*PK_ERROR_COMPILE*/) {
|
||||||
|
err_text = `[Error at:${line}] ${msg}`;
|
||||||
|
} else if (type == 1 /*PK_ERROR_RUNTIME*/) {
|
||||||
|
err_text = `Error: ${msg}`;
|
||||||
|
} else if (type == 2 /*PK_ERROR_STACKTRACE*/) {
|
||||||
|
err_text = ` [at:${line}] ${msg}`;
|
||||||
|
}
|
||||||
|
|
||||||
var out = document.getElementById("output");
|
var out = document.getElementById("output");
|
||||||
out.innerText += `[Error at:${line}]: ${AsciiToString(message)} \n`;
|
out.innerText += err_text + '\n';
|
||||||
},
|
},
|
||||||
|
|
||||||
js_writeFunction : function(message) {
|
js_writeFunction : function(message) {
|
||||||
|
@ -10,13 +10,15 @@
|
|||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include "pocketlang.h"
|
#include "pocketlang.h"
|
||||||
|
|
||||||
extern void js_errorPrint(const char* message, int line);
|
extern void js_errorPrint(int type, int line, const char* message);
|
||||||
extern void js_writeFunction(const char* message);
|
extern void js_writeFunction(const char* message);
|
||||||
extern const char* js_loadScript();
|
extern const char* js_loadScript();
|
||||||
|
|
||||||
void errorPrint(PKVM* vm, PKErrorType type, const char* file, int line,
|
void errorPrint(PKVM* vm, PKErrorType type, const char* file, int line,
|
||||||
const char* message) {
|
const char* message) {
|
||||||
js_errorPrint(message, line);
|
// No need to pass file (since there is only script that'll ever run on the
|
||||||
|
// browser.
|
||||||
|
js_errorPrint((int)type, line, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeFunction(PKVM* vm, const char* text) {
|
void writeFunction(PKVM* vm, const char* text) {
|
||||||
|
@ -345,6 +345,8 @@ static void reportError(Parser* parser, const char* file, int line,
|
|||||||
int length = vsprintf(message, fmt, args);
|
int length = vsprintf(message, fmt, args);
|
||||||
ASSERT(length < ERROR_MESSAGE_SIZE, "Error message buffer should not exceed "
|
ASSERT(length < ERROR_MESSAGE_SIZE, "Error message buffer should not exceed "
|
||||||
"the buffer");
|
"the buffer");
|
||||||
|
|
||||||
|
if (vm->config.error_fn == NULL) return;
|
||||||
vm->config.error_fn(vm, PK_ERROR_COMPILE, file, line, message);
|
vm->config.error_fn(vm, PK_ERROR_COMPILE, file, line, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,6 +206,10 @@ void coreToString(PKVM* vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void corePrint(PKVM* vm) {
|
void corePrint(PKVM* vm) {
|
||||||
|
// If the host appliaction donesn't provide any write function, discard the
|
||||||
|
// output.
|
||||||
|
if (vm->config.write_fn == NULL) return;
|
||||||
|
|
||||||
String* str; //< Will be cleaned by garbage collector;
|
String* str; //< Will be cleaned by garbage collector;
|
||||||
|
|
||||||
for (int i = 1; i <= ARGC; i++) {
|
for (int i = 1; i <= ARGC; i++) {
|
||||||
|
20
src/debug.c
20
src/debug.c
@ -259,18 +259,18 @@ void dumpInstructions(PKVM* vm, Function* func) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void reportStackTrace(PKVM* vm) {
|
void reportStackTrace(PKVM* vm) {
|
||||||
|
if (vm->config.error_fn == NULL) return;
|
||||||
|
|
||||||
Fiber* fiber = vm->fiber;
|
Fiber* fiber = vm->fiber;
|
||||||
Script* script = fiber->func->owner;
|
|
||||||
|
|
||||||
//vm->config.error_fn(vm, PK_ERROR_RUNTIME, NULL, -1, fiber->error )
|
vm->config.error_fn(vm, PK_ERROR_RUNTIME, NULL, -1, fiber->error->data);
|
||||||
//
|
|
||||||
//// TODO: I'm not confident about this approach.
|
|
||||||
//if (script->path != NULL) { // User script.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//} else { // "std" script.
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
for (int i = fiber->frame_count - 1; i >= 0; i--) {
|
||||||
|
CallFrame* frame = &fiber->frames[i];
|
||||||
|
Function* fn = frame->fn;
|
||||||
|
ASSERT(!fn->is_native, OOPS);
|
||||||
|
int line = fn->fn->oplines.data[frame->ip - fn->fn->opcodes.data - 1];
|
||||||
|
vm->config.error_fn(vm, PK_ERROR_STACKTRACE, fn->owner->name->data, line, fn->name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ typedef void (*pkNativeFn)(PKVM* vm);
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
||||||
// Compile time errors (syntax errors, unresolved fn, etc).
|
// Compile time errors (syntax errors, unresolved fn, etc).
|
||||||
PK_ERROR_COMPILE,
|
PK_ERROR_COMPILE = 0,
|
||||||
|
|
||||||
// Runtime error message.
|
// Runtime error message.
|
||||||
PK_ERROR_RUNTIME,
|
PK_ERROR_RUNTIME,
|
||||||
|
@ -189,6 +189,7 @@ static void blackenObject(Object* obj, PKVM* vm) {
|
|||||||
}
|
}
|
||||||
vm->bytes_allocated += sizeof(CallFrame) * fiber->frame_capacity;
|
vm->bytes_allocated += sizeof(CallFrame) * fiber->frame_capacity;
|
||||||
|
|
||||||
|
grayObject(&fiber->caller->_super, vm);
|
||||||
grayObject(&fiber->error->_super, vm);
|
grayObject(&fiber->error->_super, vm);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
@ -286,7 +287,7 @@ Script* newScript(PKVM* vm, String* name) {
|
|||||||
stringBufferInit(&script->names);
|
stringBufferInit(&script->names);
|
||||||
|
|
||||||
vmPushTempRef(vm, &script->_super);
|
vmPushTempRef(vm, &script->_super);
|
||||||
const char* fn_name = "@(ScriptLevel)";
|
const char* fn_name = "$(SourceBody)";
|
||||||
script->body = newFunction(vm, fn_name, (int)strlen(fn_name), script, false);
|
script->body = newFunction(vm, fn_name, (int)strlen(fn_name), script, false);
|
||||||
vmPopTempRef(vm);
|
vmPopTempRef(vm);
|
||||||
|
|
||||||
|
@ -336,6 +336,9 @@ struct Fiber {
|
|||||||
// Number of frame entry in frames.
|
// Number of frame entry in frames.
|
||||||
int frame_count;
|
int frame_count;
|
||||||
|
|
||||||
|
// Caller of this fiber if it has one, NULL otherwise.
|
||||||
|
Fiber* caller;
|
||||||
|
|
||||||
// Runtime error initially NULL, heap allocated.
|
// Runtime error initially NULL, heap allocated.
|
||||||
String* error;
|
String* error;
|
||||||
};
|
};
|
||||||
|
62
src/vm.c
62
src/vm.c
@ -230,8 +230,9 @@ static Var importScript(PKVM* vm, String* name, bool is_core,
|
|||||||
*is_new_script = true;
|
*is_new_script = true;
|
||||||
|
|
||||||
pkStringResult result = { false, NULL, NULL };
|
pkStringResult result = { false, NULL, NULL };
|
||||||
if (vm->config.load_script_fn != NULL)
|
if (vm->config.load_script_fn != NULL) {
|
||||||
result = vm->config.load_script_fn(vm, name->data);
|
result = vm->config.load_script_fn(vm, name->data);
|
||||||
|
}
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
vmPopTempRef(vm); // name
|
vmPopTempRef(vm); // name
|
||||||
@ -290,12 +291,15 @@ static inline void pushCallFrame(PKVM* vm, Function* fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pkSetRuntimeError(PKVM* vm, const char* message) {
|
void pkSetRuntimeError(PKVM* vm, const char* message) {
|
||||||
vm->fiber->error = stringFormat(vm, "$", message);
|
vm->fiber->error = newString(vm, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vmReportError(PKVM* vm) {
|
void vmReportError(PKVM* vm) {
|
||||||
ASSERT(HAS_ERROR(), "runtimeError() should be called after an error.");
|
ASSERT(HAS_ERROR(), "runtimeError() should be called after an error.");
|
||||||
TODO; // TODO: create debug.h
|
|
||||||
|
// TODO: pass the error to the caller of the fiber.
|
||||||
|
|
||||||
|
reportStackTrace(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: temp.
|
// FIXME: temp.
|
||||||
@ -327,16 +331,20 @@ PKInterpretResult pkInterpret(PKVM* vm, const char* file) {
|
|||||||
vmPushTempRef(vm, &name->_super);
|
vmPushTempRef(vm, &name->_super);
|
||||||
|
|
||||||
if (!resolveScriptPath(vm, &name)) {
|
if (!resolveScriptPath(vm, &name)) {
|
||||||
|
if (vm->config.error_fn != NULL) {
|
||||||
vm->config.error_fn(vm, PK_ERROR_COMPILE, NULL, -1,
|
vm->config.error_fn(vm, PK_ERROR_COMPILE, NULL, -1,
|
||||||
stringFormat(vm, "Failed to resolve path '$'.", file)->data);
|
stringFormat(vm, "Failed to resolve path '$'.", file)->data);
|
||||||
|
}
|
||||||
return PK_RESULT_COMPILE_ERROR;
|
return PK_RESULT_COMPILE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the script source.
|
// Load the script source.
|
||||||
pkStringResult res = vm->config.load_script_fn(vm, name->data);
|
pkStringResult res = vm->config.load_script_fn(vm, name->data);
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
|
if (vm->config.error_fn != NULL) {
|
||||||
vm->config.error_fn(vm, PK_ERROR_COMPILE, NULL, -1,
|
vm->config.error_fn(vm, PK_ERROR_COMPILE, NULL, -1,
|
||||||
stringFormat(vm, "Failed to load script '@'.", name)->data);
|
stringFormat(vm, "Failed to load script '@'.", name)->data);
|
||||||
|
}
|
||||||
return PK_RESULT_COMPILE_ERROR;
|
return PK_RESULT_COMPILE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,7 +398,10 @@ void _debugRuntime(PKVM* vm) {
|
|||||||
|
|
||||||
PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
||||||
|
|
||||||
register uint8_t* ip; //< Current instruction pointer.
|
// Reference to the instruction pointer in the call frame.
|
||||||
|
register uint8_t** ip;
|
||||||
|
#define IP (*ip) // Convinent macro to the instruction pointer.
|
||||||
|
|
||||||
register Var* rbp; //< Stack base pointer register.
|
register Var* rbp; //< Stack base pointer register.
|
||||||
register CallFrame* frame; //< Current call frame.
|
register CallFrame* frame; //< Current call frame.
|
||||||
register Script* script; //< Currently executing script.
|
register Script* script; //< Currently executing script.
|
||||||
@ -420,8 +431,8 @@ PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
|||||||
#define POP() (*(--vm->fiber->sp))
|
#define POP() (*(--vm->fiber->sp))
|
||||||
#define DROP() (--vm->fiber->sp)
|
#define DROP() (--vm->fiber->sp)
|
||||||
#define PEEK() (*(vm->fiber->sp - 1))
|
#define PEEK() (*(vm->fiber->sp - 1))
|
||||||
#define READ_BYTE() (*ip++)
|
#define READ_BYTE() (*IP++)
|
||||||
#define READ_SHORT() (ip+=2, (uint16_t)((ip[-2] << 8) | ip[-1]))
|
#define READ_SHORT() (IP+=2, (uint16_t)((IP[-2] << 8) | IP[-1]))
|
||||||
|
|
||||||
// Check if any runtime error exists and if so returns RESULT_RUNTIME_ERROR.
|
// Check if any runtime error exists and if so returns RESULT_RUNTIME_ERROR.
|
||||||
#define CHECK_ERROR() \
|
#define CHECK_ERROR() \
|
||||||
@ -440,16 +451,12 @@ PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
|||||||
return PK_RESULT_RUNTIME_ERROR; \
|
return PK_RESULT_RUNTIME_ERROR; \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
// Store the current frame to vm's call frame before pushing a new frame.
|
// Load the last call frame to vm's execution variables to resume/run the
|
||||||
// Frames rbp will set once it created and will never change.
|
// function.
|
||||||
#define STORE_FRAME() frame->ip = ip
|
|
||||||
|
|
||||||
// Update the call frame and ip once vm's call frame pushed or popped.
|
|
||||||
// fuction call, return or done running imported script.
|
|
||||||
#define LOAD_FRAME() \
|
#define LOAD_FRAME() \
|
||||||
do { \
|
do { \
|
||||||
frame = &vm->fiber->frames[vm->fiber->frame_count-1]; \
|
frame = &vm->fiber->frames[vm->fiber->frame_count-1]; \
|
||||||
ip = frame->ip; \
|
ip = &(frame->ip); \
|
||||||
rbp = frame->rbp; \
|
rbp = frame->rbp; \
|
||||||
script = frame->fn->owner; \
|
script = frame->fn->owner; \
|
||||||
} while (false)
|
} while (false)
|
||||||
@ -663,9 +670,8 @@ PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
|||||||
CHECK_ERROR();
|
CHECK_ERROR();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
STORE_FRAME();
|
|
||||||
pushCallFrame(vm, fn);
|
pushCallFrame(vm, fn);
|
||||||
LOAD_FRAME();
|
LOAD_FRAME(); //< Load the top frame to vm's execution variables.
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -681,13 +687,10 @@ PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
|||||||
Var* container = (vm->fiber->sp - 3);
|
Var* container = (vm->fiber->sp - 3);
|
||||||
uint16_t jump_offset = READ_SHORT();
|
uint16_t jump_offset = READ_SHORT();
|
||||||
|
|
||||||
bool is_done = varIterate(vm, *container, iterator, iter_value);
|
bool iterated = varIterate(vm, *container, iterator, iter_value);
|
||||||
CHECK_ERROR();
|
CHECK_ERROR();
|
||||||
if (!is_done) {
|
if (!iterated) {
|
||||||
DROP(); //< Iter value.
|
IP += jump_offset;
|
||||||
DROP(); //< Iterator.
|
|
||||||
DROP(); //< Container.
|
|
||||||
ip += jump_offset;
|
|
||||||
}
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
@ -695,14 +698,14 @@ PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
|||||||
OPCODE(JUMP):
|
OPCODE(JUMP):
|
||||||
{
|
{
|
||||||
uint16_t offset = READ_SHORT();
|
uint16_t offset = READ_SHORT();
|
||||||
ip += offset;
|
IP += offset;
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
OPCODE(LOOP):
|
OPCODE(LOOP):
|
||||||
{
|
{
|
||||||
uint16_t offset = READ_SHORT();
|
uint16_t offset = READ_SHORT();
|
||||||
ip -= offset;
|
IP -= offset;
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,7 +715,7 @@ PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
|||||||
Var cond = POP();
|
Var cond = POP();
|
||||||
uint16_t offset = READ_SHORT();
|
uint16_t offset = READ_SHORT();
|
||||||
if (toBool(cond)) {
|
if (toBool(cond)) {
|
||||||
ip += offset;
|
IP += offset;
|
||||||
}
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
@ -722,14 +725,18 @@ PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
|||||||
Var cond = POP();
|
Var cond = POP();
|
||||||
uint16_t offset = READ_SHORT();
|
uint16_t offset = READ_SHORT();
|
||||||
if (!toBool(cond)) {
|
if (!toBool(cond)) {
|
||||||
ip += offset;
|
IP += offset;
|
||||||
}
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
OPCODE(RETURN):
|
OPCODE(RETURN):
|
||||||
{
|
{
|
||||||
|
// TODO: handle caller fiber.
|
||||||
|
|
||||||
Var ret = POP();
|
Var ret = POP();
|
||||||
|
|
||||||
|
// Pop the last frame.
|
||||||
vm->fiber->frame_count--;
|
vm->fiber->frame_count--;
|
||||||
|
|
||||||
// If no more call frames. We're done.
|
// If no more call frames. We're done.
|
||||||
@ -754,6 +761,7 @@ PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
|||||||
Var on = POP();
|
Var on = POP();
|
||||||
String* name = script->names.data[READ_SHORT()];
|
String* name = script->names.data[READ_SHORT()];
|
||||||
PUSH(varGetAttrib(vm, on, name));
|
PUSH(varGetAttrib(vm, on, name));
|
||||||
|
CHECK_ERROR();
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -762,6 +770,7 @@ PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
|||||||
Var on = PEEK();
|
Var on = PEEK();
|
||||||
String* name = script->names.data[READ_SHORT()];
|
String* name = script->names.data[READ_SHORT()];
|
||||||
PUSH(varGetAttrib(vm, on, name));
|
PUSH(varGetAttrib(vm, on, name));
|
||||||
|
CHECK_ERROR();
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -772,6 +781,7 @@ PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
|||||||
String* name = script->names.data[READ_SHORT()];
|
String* name = script->names.data[READ_SHORT()];
|
||||||
varSetAttrib(vm, on, name, value);
|
varSetAttrib(vm, on, name, value);
|
||||||
PUSH(value);
|
PUSH(value);
|
||||||
|
CHECK_ERROR();
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -864,7 +874,7 @@ PKInterpretResult vmRunScript(PKVM* vm, Script* _script) {
|
|||||||
OPCODE(MOD):
|
OPCODE(MOD):
|
||||||
{
|
{
|
||||||
Var r = POP(), l = POP();
|
Var r = POP(), l = POP();
|
||||||
PUSH(varModulo(vm, r, l));
|
PUSH(varModulo(vm, l, r));
|
||||||
CHECK_ERROR();
|
CHECK_ERROR();
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
17
test/examples/fib.pk
Normal file
17
test/examples/fib.pk
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
## Fib test.
|
||||||
|
|
||||||
|
res = ''
|
||||||
|
|
||||||
|
def fib(n)
|
||||||
|
a = 0; b = 1
|
||||||
|
for _ in 0..n
|
||||||
|
res += to_string(a) + " "
|
||||||
|
temp = a;
|
||||||
|
a = b;
|
||||||
|
b += temp;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fib(10)
|
||||||
|
assert(res == '0 1 1 2 3 5 8 13 21 34 ')
|
@ -1,3 +1,8 @@
|
|||||||
|
|
||||||
|
## Prime numbers.
|
||||||
|
|
||||||
|
res = ''
|
||||||
|
|
||||||
def is_prime(n)
|
def is_prime(n)
|
||||||
if n < 2 then return false end
|
if n < 2 then return false end
|
||||||
for i in 2..n
|
for i in 2..n
|
||||||
@ -6,11 +11,13 @@ def is_prime(n)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
def print_all_primes(n)
|
def get_all_primes(n)
|
||||||
for i in 0..n
|
for i in 0..n
|
||||||
if is_prime(i) then print(i) end
|
if is_prime(i)
|
||||||
|
res += to_string(i) + ' '
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
get_all_primes(20)
|
||||||
print_all_primes(10)
|
assert(res == '2 3 5 7 11 13 17 19 ')
|
@ -1,16 +0,0 @@
|
|||||||
|
|
||||||
## Local variable test.
|
|
||||||
|
|
||||||
seq = ''
|
|
||||||
def fib(n)
|
|
||||||
a = 0; b = 1
|
|
||||||
for _ in 0..n
|
|
||||||
seq += to_string(a) + " "
|
|
||||||
temp = a;
|
|
||||||
a = b;
|
|
||||||
b += temp;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
fib(10)
|
|
||||||
assert(seq == '0 1 1 2 3 5 8 13 21 34 ')
|
|
@ -4,8 +4,8 @@ set files=( ^
|
|||||||
lang\basics.pk ^
|
lang\basics.pk ^
|
||||||
lang\import.pk ^
|
lang\import.pk ^
|
||||||
lang\if.pk ^
|
lang\if.pk ^
|
||||||
lang\locals.pk ^
|
|
||||||
^
|
^
|
||||||
|
examples\fib.pk ^
|
||||||
examples\prime.pk ^
|
examples\prime.pk ^
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user