Skip to content

Commit

Permalink
Merge pull request #635 from dictu-lang/feature/attribute
Browse files Browse the repository at this point in the history
Attributes
  • Loading branch information
Jason2605 authored Aug 20, 2023
2 parents 2ec1e8e + c103173 commit ac7327a
Show file tree
Hide file tree
Showing 16 changed files with 255 additions and 226 deletions.
42 changes: 21 additions & 21 deletions docs/docs/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ A big part of the OOP paradigm is encapsulation, the fact that the outside inter
internal to the class do not need to be known to the user of the interface. Dictu manages this concept much the same as other languages
through access levels. Unlike other languages, Dictu only has two access levels, `public` or `private`. If a method or instance variable
is marked as `private` it is only accessible from within the class itself. To mark an instance variable as private it can be done in two
ways, via [implicit properties](#implicit-properties) or by marking the property as private (note this must be done before defining the
property otherwise it will be publically visible). To mark a method as private, preface the name with `private`.
ways, via [implicit attributes](#implicit-attributes) or by marking the attribute as private (note this must be done before defining the
attribute otherwise it will be publicly visible). To mark a method as private, preface the name with `private`.

```js
class SomeClass {
Expand All @@ -54,7 +54,7 @@ class SomeClass {
}

print(SomeClass(10).getX()); // 10
print(SomeClass(10).x); // Cannot access private property 'x' on 'SomeClass' instance.
print(SomeClass(10).x); // Cannot access private attribute 'x' on 'SomeClass' instance.
```

## Constructor
Expand All @@ -72,9 +72,9 @@ class SomeClass {
SomeClass("Object created!"); // Object created!
```

### Implicit properties
### Implicit Attributes

Dictu actually has a way to define properties on the object without explicitly setting each variable passed into the constructor on the object through `this`.
Dictu actually has a way to define attributes on the object without explicitly setting each variable passed into the constructor on the object through `this`.
If `var` is used the instance variable has public visibility, if `private` is used the instance variable has private visibility.

```cs
Expand All @@ -92,8 +92,8 @@ The `var` or `private` keywords are optional on the constructor parameters, and
```cs
class SomeClass {
init(var a, b, c, var d, private e) {
// b and c are not set as instance properties
// e is set as a private property
// b and c are not set as instance attributes
// e is set as a private attribute
}
}

Expand Down Expand Up @@ -210,7 +210,7 @@ print(myObject.x); // 10
Attempting to access an attribute of an object that does not exist will throw a runtime error, and instead before accessing an attribute that may not be there, you should check
if the object has the given attribute. This is done via `hasAttribute`.

Note: Will only check properties with public visibility.
Note: Will only check attributes with public visibility.

```cs
class Test {
Expand All @@ -223,15 +223,15 @@ var myObject = Test();
print(myObject.hasAttribute("x")); // true
print(myObject.hasAttribute("y")); // false
print(myObject.z); // Undefined property 'z'.
print(myObject.z); // Undefined attribute 'z'.
```

### getAttribute(String) -> value
### getAttribute(String) -> Value

Sometimes in Dictu we may wish to access an attribute of an object without knowing the attribute until runtime. We can do this via the `getAttribute` method.
This method takes a string and an optional default value and returns either the attribute value or the default value (if there is no attribute and no default value, nil is returned).

Note: Will only retrieve properties with public visibility.
Note: Will only retrieve attributes with public visibility.

```cs
class Test {
Expand All @@ -247,9 +247,9 @@ print(myObject.getAttribute("y", 100)); // 100
print(myObject.getAttribute("y")); // nil
```

### getAttributes() -> List
### getAttributes() -> Dict

The `getAttributes` method returns all public attributes on the given instance of a class.
The `getAttributes` method returns all class variables / constants, public methods and public attributes.

```cs
class Test {
Expand All @@ -259,14 +259,14 @@ class Test {
}

var myObject = Test();
print(myObject.getAttributes()); // ["x"]
print(myObject.getAttributes()); // {"fields": ["_name"], "methods": ["init"], "attributes": ["_class", "x"]}
```

### setAttribute(String, value)
### setAttribute(String, Value)

Similar concept to `getAttribute` however this allows us to set an attribute on an instance.

Note: Will set a property with public visibility.
Note: Will set a attribute with public visibility.

```cs
class Test {
Expand All @@ -282,10 +282,10 @@ print(myObject.x); // 100

### Optional Chaining

Optional chaining allows you to read a property or method of an instance without explicitly having to check for `nil` before
Optional chaining allows you to read a attribute or method of an instance without explicitly having to check for `nil` before
attempting to access.

**Note:** If the left hand value is not nil the property / method **must** still exist when attempting to access otherwise a runtime error will occur.
**Note:** If the left hand value is not nil the attribute / method **must** still exist when attempting to access otherwise a runtime error will occur.

```js
class Test {
Expand All @@ -303,8 +303,8 @@ class Test {
// Here there is no explicit nil check.
print(Test().someMethod()?.someOtherMethod()); // nil

// If the operand is not nil the method / property must exist
print(Test()?.unknownMethod()); // Undefined property 'unknownMethod'.
// If the operand is not nil the method / attribute must exist
print(Test()?.unknownMethod()); // Undefined attribute 'unknownMethod'.
```
### _class
Expand Down Expand Up @@ -674,7 +674,7 @@ class ClassWithMethodAnnotation {
}
```
Annotations are access via the `.classAnnotations`, `.methodAnnotations` and `.fieldAnnotations` properties available on all classes.
Annotations are access via the `.classAnnotations`, `.methodAnnotations` and `.fieldAnnotations` attributes available on all classes.
For class annotations, the returned data structure returned is a dictionary with keys set to the names of the annotations and their values if present. If no value is provided to the annotation, the value associated with the key is set to `nil`.
Expand Down
12 changes: 6 additions & 6 deletions docs/docs/standard-lib/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,24 +93,24 @@ httpClient.post("https://httpbin.org/post", {"test": 10});
### Response

Both HTTP.get(), HTTP.post(), httpClient.get(), and httpClient.post() return a Result that unwraps a Response object on success, or nil on error.
The Response object returned has 3 public properties, "content", "headers" and "statusCode". "content" is the actual content returned from the
The Response object returned has 3 public attributes, "content", "headers" and "statusCode". "content" is the actual content returned from the
HTTP request as a string, "headers" is a list of all the response headers and "statusCode" is a number denoting the status code from
the response

#### Quick Reference Table
##### Properties
##### Attributes

| Property | Description |
| Attribute | Description |
| ---------- | ------------------------------------------------- |
| content | Raw string content returned from the HTTP request |
| headers | A list of headers returned from the HTTP request |
| statusCode | The status code returned from the HTTP request |

##### Methods

| Method | Description |
| ------ | ------------------------------------ |
| json | Convert the content property to JSON |
| Method | Description |
| ------ | ------------------------------------- |
| json | Convert the content attribute to JSON |

Example response from [httpbin.org](https://httpbin.org)

Expand Down
2 changes: 1 addition & 1 deletion examples/templateEngine.du
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Template {
// matches the fields in the class to the template
// fields and replaces them with the class values.
render() {
const classAttrs = this.klass.getAttributes()["properties"];
const classAttrs = this.klass.getAttributes()["attributes"];
var rendered = this.tmpl;

classAttrs.forEach(def(attr) => {
Expand Down
5 changes: 1 addition & 4 deletions src/optionals/argparse/argparse-source.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@
"}\n" \
"\n" \
"class Parser {\n" \
" private name;\n" \
" private desc;\n" \
" private userUsage;\n" \
" private args;\n" \
"\n" \
" var preArgs = [];\n" \
" var required = [];\n" \
"\n" \
" init(var name, var desc, var userUsage) {\n" \
" init(private name, private desc, private userUsage) {\n" \
" this.args = Args(name, desc);\n" \
" }\n" \
"\n" \
Expand Down
5 changes: 1 addition & 4 deletions src/optionals/argparse/argparse.du
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@ class Args {
}

class Parser {
private name;
private desc;
private userUsage;
private args;

var preArgs = [];
var required = [];

init(var name, var desc, var userUsage) {
init(private name, private desc, private userUsage) {
this.args = Args(name, desc);
}

Expand Down
6 changes: 3 additions & 3 deletions src/optionals/http/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,17 +377,17 @@ static ObjInstance *endRequest(DictuVM *vm, CURL *curl, Response response, bool

ObjString *string = copyString(vm, "content", 7);
push(vm, OBJ_VAL(string));
tableSet(vm, &responseInstance->publicFields, string, OBJ_VAL(content));
tableSet(vm, &responseInstance->publicAttributes, string, OBJ_VAL(content));
pop(vm);

string = copyString(vm, "headers", 7);
push(vm, OBJ_VAL(string));
tableSet(vm, &responseInstance->publicFields, string, OBJ_VAL(response.headers));
tableSet(vm, &responseInstance->publicAttributes, string, OBJ_VAL(response.headers));
pop(vm);

string = copyString(vm, "statusCode", 10);
push(vm, OBJ_VAL(string));
tableSet(vm, &responseInstance->publicFields, string, NUMBER_VAL(response.statusCode));
tableSet(vm, &responseInstance->publicAttributes, string, NUMBER_VAL(response.statusCode));
pop(vm);

// Pop instance
Expand Down
84 changes: 42 additions & 42 deletions src/vm/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -698,86 +698,86 @@ static void dot(Compiler *compiler, LangToken previousToken, bool canAssign) {
privatePropertyExists(identifier, compiler))) {
if (canAssign && match(compiler, TOKEN_EQUAL)) {
expression(compiler);
emitBytes(compiler, OP_SET_PRIVATE_PROPERTY, name);
emitBytes(compiler, OP_SET_PRIVATE_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_PLUS_EQUALS)) {
emitBytes(compiler, OP_GET_PRIVATE_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_PRIVATE_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_ADD);
emitBytes(compiler, OP_SET_PRIVATE_PROPERTY, name);
emitBytes(compiler, OP_SET_PRIVATE_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_MINUS_EQUALS)) {
emitBytes(compiler, OP_GET_PRIVATE_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_PRIVATE_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_SUBTRACT);
emitBytes(compiler, OP_SET_PRIVATE_PROPERTY, name);
emitBytes(compiler, OP_SET_PRIVATE_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_MULTIPLY_EQUALS)) {
emitBytes(compiler, OP_GET_PRIVATE_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_PRIVATE_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_MULTIPLY);
emitBytes(compiler, OP_SET_PRIVATE_PROPERTY, name);
emitBytes(compiler, OP_SET_PRIVATE_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_DIVIDE_EQUALS)) {
emitBytes(compiler, OP_GET_PRIVATE_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_PRIVATE_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_DIVIDE);
emitBytes(compiler, OP_SET_PRIVATE_PROPERTY, name);
emitBytes(compiler, OP_SET_PRIVATE_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_AMPERSAND_EQUALS)) {
emitBytes(compiler, OP_GET_PRIVATE_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_PRIVATE_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_BITWISE_AND);
emitBytes(compiler, OP_SET_PRIVATE_PROPERTY, name);
emitBytes(compiler, OP_SET_PRIVATE_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_CARET_EQUALS)) {
emitBytes(compiler, OP_GET_PRIVATE_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_PRIVATE_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_BITWISE_XOR);
emitBytes(compiler, OP_SET_PRIVATE_PROPERTY, name);
emitBytes(compiler, OP_SET_PRIVATE_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_PIPE_EQUALS)) {
emitBytes(compiler, OP_GET_PRIVATE_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_PRIVATE_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_BITWISE_OR);
emitBytes(compiler, OP_SET_PRIVATE_PROPERTY, name);
emitBytes(compiler, OP_SET_PRIVATE_ATTRIBUTE, name);
} else {
emitBytes(compiler, OP_GET_PRIVATE_PROPERTY, name);
emitBytes(compiler, OP_GET_PRIVATE_ATTRIBUTE, name);
}
} else {
if (canAssign && match(compiler, TOKEN_EQUAL)) {
expression(compiler);
emitBytes(compiler, OP_SET_PROPERTY, name);
emitBytes(compiler, OP_SET_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_PLUS_EQUALS)) {
emitBytes(compiler, OP_GET_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_ADD);
emitBytes(compiler, OP_SET_PROPERTY, name);
emitBytes(compiler, OP_SET_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_MINUS_EQUALS)) {
emitBytes(compiler, OP_GET_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_SUBTRACT);
emitBytes(compiler, OP_SET_PROPERTY, name);
emitBytes(compiler, OP_SET_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_MULTIPLY_EQUALS)) {
emitBytes(compiler, OP_GET_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_MULTIPLY);
emitBytes(compiler, OP_SET_PROPERTY, name);
emitBytes(compiler, OP_SET_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_DIVIDE_EQUALS)) {
emitBytes(compiler, OP_GET_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_DIVIDE);
emitBytes(compiler, OP_SET_PROPERTY, name);
emitBytes(compiler, OP_SET_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_AMPERSAND_EQUALS)) {
emitBytes(compiler, OP_GET_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_BITWISE_AND);
emitBytes(compiler, OP_SET_PROPERTY, name);
emitBytes(compiler, OP_SET_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_CARET_EQUALS)) {
emitBytes(compiler, OP_GET_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_BITWISE_XOR);
emitBytes(compiler, OP_SET_PROPERTY, name);
emitBytes(compiler, OP_SET_ATTRIBUTE, name);
} else if (canAssign && match(compiler, TOKEN_PIPE_EQUALS)) {
emitBytes(compiler, OP_GET_PROPERTY_NO_POP, name);
emitBytes(compiler, OP_GET_ATTRIBUTE_NO_POP, name);
expression(compiler);
emitByte(compiler, OP_BITWISE_OR);
emitBytes(compiler, OP_SET_PROPERTY, name);
emitBytes(compiler, OP_SET_ATTRIBUTE, name);
} else {
emitBytes(compiler, OP_GET_PROPERTY, name);
emitBytes(compiler, OP_GET_ATTRIBUTE, name);
}
}
}
Expand Down Expand Up @@ -907,7 +907,7 @@ static void beginFunction(Compiler *compiler, Compiler *fnCompiler, FunctionType
fnCompiler->function->propertyIndexes[i] = indexes[i];
}

emitBytes(fnCompiler, OP_SET_INIT_PROPERTIES, makeConstant(fnCompiler, OBJ_VAL(fnCompiler->function)));
emitBytes(fnCompiler, OP_SET_INIT_ATTRIBUTES, makeConstant(fnCompiler, OBJ_VAL(fnCompiler->function)));
}

if (fnCompiler->function->privatePropertyCount > 0) {
Expand All @@ -922,7 +922,7 @@ static void beginFunction(Compiler *compiler, Compiler *fnCompiler, FunctionType
fnCompiler->function->privatePropertyIndexes[i] = privateIndexes[i];
}

emitBytes(fnCompiler, OP_SET_PRIVATE_INIT_PROPERTIES, makeConstant(fnCompiler, OBJ_VAL(fnCompiler->function)));
emitBytes(fnCompiler, OP_SET_PRIVATE_INIT_ATTRIBUTES, makeConstant(fnCompiler, OBJ_VAL(fnCompiler->function)));
}
}

Expand Down Expand Up @@ -2117,15 +2117,15 @@ static int getArgCount(uint8_t *code, const ValueArray constants, int ip) {
case OP_SET_MODULE:
case OP_GET_UPVALUE:
case OP_SET_UPVALUE:
case OP_GET_PROPERTY:
case OP_GET_PRIVATE_PROPERTY:
case OP_GET_PROPERTY_NO_POP:
case OP_GET_PRIVATE_PROPERTY_NO_POP:
case OP_SET_PROPERTY:
case OP_SET_PRIVATE_PROPERTY:
case OP_GET_ATTRIBUTE:
case OP_GET_PRIVATE_ATTRIBUTE:
case OP_GET_ATTRIBUTE_NO_POP:
case OP_GET_PRIVATE_ATTRIBUTE_NO_POP:
case OP_SET_ATTRIBUTE:
case OP_SET_PRIVATE_ATTRIBUTE:
case OP_SET_CLASS_VAR:
case OP_SET_INIT_PROPERTIES:
case OP_SET_PRIVATE_INIT_PROPERTIES:
case OP_SET_INIT_ATTRIBUTES:
case OP_SET_PRIVATE_INIT_ATTRIBUTES:
case OP_GET_SUPER:
case OP_METHOD:
case OP_IMPORT:
Expand Down
Loading

0 comments on commit ac7327a

Please sign in to comment.