Skip to content

Commit

Permalink
Merge pull request #539 from dictu-lang/feature/object_from
Browse files Browse the repository at this point in the history
Object.createFrom()
  • Loading branch information
Jason2605 committed Oct 12, 2022
2 parents 02acb1b + d177afa commit 5b6bd4f
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 1 deletion.
53 changes: 53 additions & 0 deletions docs/docs/standard-lib/object.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
layout: default
title: Object
nav_order: 17
parent: Standard Library
---

# Object
{: .no_toc }

## Table of contents
{: .no_toc .text-delta }

1. TOC
{:toc}

---

## Object

To make use of the Object module an import is required.

```cs
import Object;
```

### Object.getClassRef(string)

This method will attempt to get a class reference from the class name provided as a string.

Returns a Result and unwraps to an Object upon success.

**NOTE:** This currently only works if the class is defined in the global scope

```cs
class Test {}

Object.getClassRef("Test").unwrap(); // <Cls Test>
```

### Object.createFrom(string)

This method will attempt to create a new object from the class name provided as a string.

Returns a Result and unwraps to an Object upon success.

**NOTE:** This currently only works if the class is defined in the global scope

```cs
class Test {}

Object.createFrom("Test").unwrap(); // <Test instance>
```
3 changes: 2 additions & 1 deletion scripts/generate.du
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ var files = [
'src/vm/datatypes/result/result',
'src/optionals/unittest/unittest',
'src/optionals/env/env',
'src/optionals/http/http'
'src/optionals/http/http',
'src/optionals/object/object'
];

for (var i = 0; i < files.len(); i += 1) {
Expand Down
9 changes: 9 additions & 0 deletions src/optionals/object/object-source.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#define DICTU_OBJECT_SOURCE "import Object;\n" \
"\n" \
"def createFrom(className, ...arguments) {\n" \
" return Object.__getClassRef(className).matchWrap(\n" \
" def (klass) => klass(...arguments),\n" \
" def (error) => error\n" \
" );\n" \
"}\n" \

69 changes: 69 additions & 0 deletions src/optionals/object/object.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "object.h"

#include "object-source.h"

static Value objectGetClassRefImpl(DictuVM *vm, int argCount, Value *args, bool internal) {
if (argCount != 1) {
runtimeError(vm, "getClassRef() takes 1 argument (%d given)", argCount);
return EMPTY_VAL;
}

if (!IS_STRING(args[0])) {
runtimeError(vm, "getClassRef() argument must be a string");
return EMPTY_VAL;
}

ObjString *classString = AS_STRING(args[0]);

Value klass;
CallFrame *frame;
if (internal) {
// -2 as we want to go to the callee site, not the Object.du code
frame = &vm->frames[vm->frameCount - 2];
} else {
frame = &vm->frames[vm->frameCount - 1];
}

if (tableGet(&frame->closure->function->module->values, classString, &klass) && IS_CLASS(klass)) {
return newResultSuccess(vm, klass);
}

char *error = ALLOCATE(vm, char, classString->length + 26);
memcpy(error, classString->chars, classString->length);
memcpy(error + classString->length, " class could not be found", 25);
error[classString->length + 25] = '\0';

Value result = newResultError(vm, error);

FREE_ARRAY(vm, char, error, classString->length + 26);

return result;
}

static Value objectGetClassRef(DictuVM *vm, int argCount, Value *args) {
return objectGetClassRefImpl(vm, argCount, args, false);
}

static Value objectGetClassRefInternal(DictuVM *vm, int argCount, Value *args) {
return objectGetClassRefImpl(vm, argCount, args, true);
}

Value createObjectModule(DictuVM *vm) {
ObjClosure *closure = compileModuleToClosure(vm, "Object", DICTU_OBJECT_SOURCE);

if (closure == NULL) {
return EMPTY_VAL;
}

push(vm, OBJ_VAL(closure));

/**
* Define Object methods
*/
defineNative(vm, &closure->function->module->values, "__getClassRef", objectGetClassRefInternal);
defineNative(vm, &closure->function->module->values, "getClassRef", objectGetClassRef);

pop(vm);

return OBJ_VAL(closure);
}
8 changes: 8 additions & 0 deletions src/optionals/object/object.du
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Object;

def createFrom(className, ...arguments) {
return Object.__getClassRef(className).matchWrap(
def (klass) => klass(...arguments),
def (error) => error
);
}
11 changes: 11 additions & 0 deletions src/optionals/object/object.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef dictu_object_module_h
#define dictu_object_module_h

#include <stdlib.h>

#include "../optionals.h"
#include "../../vm/vm.h"

Value createObjectModule(DictuVM *vm);

#endif //dictu_object_module_h
1 change: 1 addition & 0 deletions src/optionals/optionals.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ BuiltinModules modules[] = {
{"System", &createSystemModule, false},
{"UnitTest", &createUnitTestModule, true},
{"Inspect", &createInspectModule, false},
{"Object", &createObjectModule, true},
#ifndef DISABLE_HTTP
{"HTTP", &createHTTPModule, true},
#endif
Expand Down
1 change: 1 addition & 0 deletions src/optionals/optionals.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "sqlite.h"
#include "process.h"
#include "inspect.h"
#include "object/object.h"
#include "unittest/unittest.h"

typedef Value (*BuiltinModule)(DictuVM *vm);
Expand Down
21 changes: 21 additions & 0 deletions tests/object/createFrom.du
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* createFrom.du
*
* Testing the Object.createFrom method
*/
from UnitTest import UnitTest;

import Object;

class Test {}

class TestObjectCreateFrom < UnitTest {
testObjectCreateFrom() {
this.assertSuccess(Object.createFrom('Test'));
this.assertError(Object.createFrom('Unknown'));

this.assertType(Object.createFrom('Test').unwrap(), 'Test');
}
}

TestObjectCreateFrom().run();
7 changes: 7 additions & 0 deletions tests/object/import.du
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* import.du
*
* General import file for all the Object module tests
*/

import "createFrom.du";
1 change: 1 addition & 0 deletions tests/runTests.du
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import "modules/import.du";
import "imports/import.du";
import "random/import.du";
import "hashlib/import.du";
import "object/import.du";

// If we got here no runtime errors were thrown, therefore all tests passed.
print("All tests passed successfully!");

0 comments on commit 5b6bd4f

Please sign in to comment.