Skip to content

Commit

Permalink
Merge pull request #513 from dictu-lang/develop
Browse files Browse the repository at this point in the history
Release 0.24.0
  • Loading branch information
Jason2605 authored Mar 6, 2022
2 parents bdc951c + e613bbb commit af99968
Show file tree
Hide file tree
Showing 37 changed files with 910 additions and 100 deletions.
2 changes: 1 addition & 1 deletion docs/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: >-
color_scheme: "dictu" # Custom theme
logo: "/assets/images/dictu-logo/dictu-wordmark.svg"

version: "0.23.0"
version: "0.24.0"
github_username: dictu-lang
search_enabled: true

Expand Down
34 changes: 29 additions & 5 deletions docs/docs/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ print(Test()._class); // <Cls Test>
## Class variables
A class variable, is a variable that is defined on the class and not the instance. This means that all instances of the class will have access
A class variable is a variable that is defined on the class and not the instance. This means that all instances of the class will have access
to the class variable, and it is also shared across all instances.
```cs
Expand All @@ -332,20 +332,44 @@ class SomeClass {
}
}

print(SomeClass.classVaraible); // 10
print(SomeClass.classVariable); // 10

var x = SomeClass();
var y = SomeClass();
const x = SomeClass();
const y = SomeClass();

print(x.classVariable); // 10
print(y.classVariable); // 10

SomeClass.classVaraible = 100;
SomeClass.classVariable = 100;

print(x.classVariable); // 100
print(y.classVariable); // 100
```
## Class Constants
Exactly the same as [Class Variables](#class-variables) except that it comes with a runtime guarantee that it will not be modified.
```cs
class SomeClass {
const classVariable = 10; // This will be shared among all "SomeClass" instances

init() {
this.x = 10; // "x" is set on the instance
}
}

print(SomeClass.classVariable); // 10

const x = SomeClass();
const y = SomeClass();

print(x.classVariable); // 10
print(y.classVariable); // 10

SomeClass.classVariable = 100; // Cannot assign to class constant 'SomeClass.classVariable'.
```
## Static methods
Static methods are methods which do not reference an object, and instead belong to a class. If a method is marked as static, `this` is not passed to the object. This means static methods can be invoked without instantiating an object.
Expand Down
58 changes: 58 additions & 0 deletions docs/docs/control-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,64 @@ if (x == 6) {
print("Not going to print!");
}
```

## Switch Statement

A switch statement can be seen as a more maintainable if/else if chain. It evaluates an expression and then enters a
case block depending upon if the expression matches the expression of the case block.

The value supplied to a case block can be of any type and follows the same rules of equality as the `==` operator.

```cs
switch (10) {
case 1: {
// 10 doesn't equal 1, so this is skipped.
}

case 10: {
// Match! This block of code is executed!
}
}
```

### Default

Sometimes there may be a need for a bit of code to be executed if none of the case blocks match the expression of the switch statement. This is where
the default block comes into play.

```
switch ("string") {
case "nope": {
}
case "nope again!": {
}
default: {
// This will get executed!
}
}
```

### Multi-Value Case

Sometimes we need to execute a block of code based on a set of values. This is easily done by just supplying a comma separated list
of values to the case block.

```cs
switch (10) {
case 1, 3, 5, 7, 9: {
// 10 doesn't equal any of the supplied values, this is skipped.
}

case 0, 2, 4, 6, 8, 10: {
// Match! This block of code is executed!
}
}
```

## Loops
### While loop

Expand Down
76 changes: 45 additions & 31 deletions docs/docs/standard-lib/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import HTTP;
### HTTP.get(string, list: headers -> optional, number: timeout -> optional)

Sends a HTTP GET request to a given URL. Timeout is given in seconds.
Returns a Result and unwraps to a dictionary upon success.
Returns a Result and unwraps to a Response upon success.

```cs
HTTP.get("https://httpbin.org/get");
Expand All @@ -40,7 +40,7 @@ HTTP.get("https://httpbin.org/get", ["Content-Type: application/json"], 1);
### HTTP.post(string, dictionary: postArgs -> optional, list: headers -> optional, number: timeout -> optional)

Sends a HTTP POST request to a given URL.Timeout is given in seconds.
Returns a Result and unwraps to a dictionary upon success.
Returns a Result and unwraps to a Response upon success.

```cs
HTTP.post("https://httpbin.org/post");
Expand All @@ -51,48 +51,62 @@ HTTP.post("https://httpbin.org/post", {"test": 10}, ["Content-Type: application/

### Response

Both HTTP.get() and HTTP.post() return a Result that unwraps a dictionary on success, or nil on error.
The dictionary returned has 3 keys, "content", "headers" and "statusCode". "content" is the actual content returned from the
Both HTTP.get() and HTTP.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
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

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

```json
// GET

{"content": '{
"args": {},
const response = HTTP.get("https://httpbin.org/get").unwrap();
print(response.content);
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-5e58197f-21f34d683a951fc741f169c6"
},
"origin": "...",
"Accept": "*/*",
"Accept-Encoding": "gzip",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-620ff6d1-24de015127aa59770abce026"
},
"origin": "...",
"url": "https://httpbin.org/get"
}
', "headers": ['HTTP/1.1 200 OK', 'Date: Thu, 27 Feb 2020 19:33:19 GMT', 'Content-Type: application/json', 'Content-Length: 220', 'Connection: keep-alive', 'Server: gunicorn/19.9.0', 'Access-Control-Allow-Origin: *', 'Access-Control-Allow-Credentials: true'], "statusCode": 200}
print(response.headers);
["HTTP/2 200 ", "date: Fri, 18 Feb 2022 19:43:13 GMT", "content-type: application/json", "content-length: 254", "server: gunicorn/19.9.0", "access-control-allow-origin: *", "access-control-allow-credentials: true"]

print(response.statusCode);
200

// POST

{"content": '{
"args": {},
"data": "",
"files": {},
"form": {
"test": "10"
},
const response = HTTP.post("https://httpbin.org/post").unwrap();
print(response.content);
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Content-Length": "8",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-5e5819ac-7e6a3cef0546c7606a34aa73"
},
"json": null,
"origin": "...",
"Accept": "*/*",
"Accept-Encoding": "gzip",
"Content-Length": "0",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-620ff777-311a6db4398c1f5325a22f8a"
},
"json": null,
"origin": "...",
"url": "https://httpbin.org/post"
}
', "headers": ['HTTP/1.1 200 OK', 'Date: Thu, 27 Feb 2020 19:34:04 GMT', 'Content-Type: application/json', 'Content-Length: 390', 'Connection: keep-alive', 'Server: gunicorn/19.9.0', 'Access-Control-Allow-Origin: *', 'Access-Control-Allow-Credentials: true'], "statusCode": 200}
```

print(response.headers);
["HTTP/2 200 ", "date: Fri, 18 Feb 2022 19:45:59 GMT", "content-type: application/json", "content-length: 404", "server: gunicorn/19.9.0", "access-control-allow-origin: *", "access-control-allow-credentials: true"]

print(response.statusCode);
200
```

#### Response.json()
To quickly convert the raw string contained within the Response object we can use the helper `.json` method.
This works exactly the same as `JSON.parse()` and will return a Result object.
49 changes: 49 additions & 0 deletions examples/openweathermap.du
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Example of how to use the HTTP module and JSON modules to interact with the
* OpenWeatherMap REST API. This can serve as a base to extend with more features.
*/

import Env;
import HTTP;
import JSON;
import System;

const BASE_URL = "http://api.openweathermap.org/data/2.5/weather?";

class Client {
private token;

init(units, lang, token) {
this.units = units;
this.lang = lang;
this.token = token;
}

current(name) {
var url = BASE_URL;
url = url + "appid=" + this.token;
url = url + "&q=" + name;
url = url + "&units=" + this.units;
url = url + "&lang=" + this.lang;

const res = HTTP.get(url);
return JSON.parse(res.unwrap()["content"]).unwrap();
}
}

// main
{
const token = Env.get("OWM_TOKEN");
if (not token) {
print("error: OWM_TOKEN required to be set in the environment");
System.exit(1);
}

const location = "Phoenix";

const client = Client("F", "en", token);
const current = client.current(location);

print("Current Weather Data for: {} \n\n{}\n".format(location, current));
}

2 changes: 2 additions & 0 deletions examples/runExamples.du
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ import "inheritance.du";
import "isPalindrome.du";
import "factorial.du";
import "pathWalker.du";
import "structured_logger.du";
import "template_engine.du";
82 changes: 82 additions & 0 deletions examples/structured_logger.du
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* Module logger provides a structured logger. The structured
* format is JSON.
*/

import JSON;
import System;

/**
* class Log implements a simple structured logger
* that outputs to either stdout or a given file.
*/
class Log {
private output;

init(output="") {
this.output = "";
if (output.len() > 1) {
this.output = output;
}
}

private set_level(level) {
this.entry = {"level": level};
}

private run(msg, fields) {
this.entry["timestamp"] = System.time();

if (fields) {
fields.keys().forEach(
def(entry) => this.entry[entry] = fields[entry]
);
}
this.entry["msg"] = msg;

const j = JSON.parse(this.entry.toString());

if (this.output.len() > 1) {
with(this.output, "a") {
file.writeLine(j.unwrap().toString());
}
} else {
print(j.unwrap());
}
}

info(msg, fields=nil) {
this.set_level("info");
this.run(msg, fields);
}

warn(msg, fields=nil) {
this.set_level("warn");
this.run(msg, fields);
}

error(msg, fields=nil) {
this.set_level("error");
this.run(msg, fields);
}

debug(msg, fields=nil) {
this.set_level("debug");
this.run(msg, fields);
}

trace(msg, fields=nil) {
this.set_level("trace");
this.run(msg, fields);
}
}

// main
{
const log = Log();
log.info("starting application");

System.sleep(2);

log.info("shutting down application", {"extra-field-1": "more data"});
}
Loading

0 comments on commit af99968

Please sign in to comment.