Commit Graph

1845 Commits

Author SHA1 Message Date
Scott Olsen
6c551a104b
fix: fix errors with set! (#1100)
Notably, don't type check dynamic bindings (which can be set to
whatever) and eliminate a hang that resulted from not handling an error
at the end of the `set!` call. Also refactors some of the code in
efforts to make it a bit cleaner.

Also adds an error when `set!` can't find the variable one calls set!
on.
2020-12-24 16:20:07 +01:00
Scott Olsen
d420635762
feat: overwrite existing interface implementations (#1094)
* feat: overwrite existing interface implementations

This commit alters the behavior of interfaces so that implementations
with the same type signature will overwrite previous implementations
with that signature--before this was a runtime error.

Previously, if a user defined two distinctly named implementations of an
interface that shared a type, Carp would panic and error at runtime if
the interface was called and resolved to the type, since it couldn't
decide which implementation to use from the type alone. After this
commit, we instead issue a warning and overwrite existing
implementations of the same type, so that defining:

```
(defn foo [] 0)
(implements zero foo)
```

will replace `Int.zero` in the `zero` interface's implementation path
list and won't result in a runtime error--instead `foo` will be called
when `zero` is called in a context in which it returns an int:

```
[WARNING] An implementation of the interface zero with type (Fn [] Int)
already exists: Int.zero. It will be replaced by the implementation:
foo.
This may break a bunch of upstream code!
```

test/interface.carp also has a concrete illustration of this case.

* chore: address hlint suggestions

* fix: don't print overridden interface implementations in info

This commit updates our handling of interface overrides to remove
interfaces from the implements meta of a function that was overridden by
a new implementation.

Similarly, this refactors primitiveInfo to prevent printing binders that
do not actually implement an interface.

* refactor: incorporate @TimDeve's error message suggestion
2020-12-23 22:24:52 +01:00
Erik Svedäng
dd3ce88ced fix: Use 'pretty' instead of 'show' in "unresolved generic type" error 2020-12-23 09:39:00 +01:00
jacereda
32d7396174
chore: Fix hlint warnings (#1086) 2020-12-22 17:44:44 +01:00
Veit Heller
e396863719
feat: Evaluate symbols for statics in REPL (#1090)
* feat: evaluate defs and defns in repl

* fix: better handling of static symbol evaluation

* refactor: include feedback by @scolsen (thanks)

* refactor: incorporate feedback by @eriksvedang into resolver code

* refactor: rename shouldResolve to resolver
2020-12-22 15:53:55 +01:00
Veit Heller
3ecf99fb5f
feat: Add parse command (#1092)
* feat: add parse command

* refactor: pull pure out of case in commandParse (thanks @jacereda)
2020-12-22 13:43:33 +01:00
Scott Olsen
856171ef16
Support defining types in modules (BREAKING) (#1084)
* fix: don't set the inner env to globals in type mods

Previously, we set the inner environment of a type generated module to
the global env in cases where the overarching context didn't have an
inner env. This leads to problems where by the recognition of modules is
inconsistent, and one can't use the names of types as submodules in
certain circumstances.

This commit fixes that issue.

* refactor: refactor primitiveDefmodule

This refactor fixes a issues with meta information on submodules, for
instance, sigs on submodule functions used to result in a compiler error
about ambiguous identifiers. This fixes that.

Unfortunately, I don't have a precise idea about what exactly was wrong
with the original definition of this function. My suspicion is that the
recursion originally altered submodule paths in the wrong way, but I'm
not certain. In any case it's fixed.

* fix: ensure macros are expanded in the correct module

Previously, macro expansions folded over all forms after the top level
form, without performing any context updates on encountered
`defmodules`. This created an issue in which macro calls that produced
new bindings, "meta stubs", were *hoisted* out of submodules and into
the top-level module, creating duplicate definitions.

This commit fixes that issue by adding a special case for defmodule in
macroExpand.

* fix: ensure submodules and globals don't conflict

Previously, our module lookups during new module definition always
eventually fell back to the global environment, which caused submodules
that happen to share a name with a global module to be confused with the
global module. This change fixes that, so now one can define both
`Dynamic` (global) and `Foo.Dynamic` without issue.

* fix: remove old prefixes from vector tests

Commit 7b7cb5d1e replaced /= with a generic function. However, the
vector tests still called the specific Vector variants of this function,
which were removed when the generic was introduced. After recent
changes, these calls are now (correctly) identified as erroneous. My
guess is that they only worked in the past because of problems with our
lookups.

* chore: format code

* feat!: support defining types in modules

This commit adds support for defining types (using deftype) in modules.
Previously, all types were hoisted to the top level of the type
environment. After this commit, the type environment supports defining
nested modules just like the value env, so, calling the following:

```
(defmodule Foo (deftype Bar Baz))
```

Adds the following to the type env:

```
Foo : Module = {
    Bar : Type
}
```

and the following to the value env:

```
Foo : Module = {
    Bar : Module = {
        Baz : (Fn [] Foo.Bar)
        copy : (Fn [(Ref Foo.Bar q)] Foo.Bar)
        delete : (Fn [Foo.Bar] ())
        get-tag : (Fn [(Ref Foo.Bar q)] Int)
        prn : (Fn [(Ref Foo.Bar q)] String)
        str : (Fn [(Ref Foo.Bar q)] String)
    }
}

```

Such a type is *distinct* from any type defined at the top level that
happens to also have the name `Bar`.

This commit also updates info and tests to account for types in modules.

BREAKING CHANGE: This change is breaking since it alters the names of
types that were previously defined in modules. A good example of this is
the `Id` type in the `Color` module. Previously, one could refer to this
type by simply typing `Id` since it was hoisted to the top level. Now it
*must* be referred to by `Color.Id` since `Id` at the top level of the
type env and `Color.Id` (Id in the color module) are considered to be
distinct types.

* chore: format code

* refactor: use concat instead of intercalate

* chore: remove excess parentheses

* chore: Add todo to return IO () in printIfFound
2020-12-22 13:27:57 +01:00
Veit Heller
95cd7852ac
refactor: remove outdated already visited trace (#1091) 2020-12-22 10:31:18 +01:00
Erik Svedäng
6f7aeaff73
feat: 'delete' interface (deciding whether a type is managed or not) (#1061)
* feat: 'delete' interface (deciding whether a type is managed or not)

* refactor: Move implements function to Interface module

* feat: Automatically implement 'delete' for types defined with `deftype`

* fix: Don't implement `delete` for Pointer

* refactor: Clarify `memberInfo` function

* fix: Also check if function types are managed

* fix: Implement 'delete' for String and StaticArray.

* fix: Manage String and Pattern. Tests run!

* feat: Add `managed?` primitive

* docs: Note about primitiveIsManaged

* test: Basic test cases for managed / nonmanaged external types

* test: Make sure `managed?` primitive works

* test: Inactivate sanitizer since we're creating leaks intentionally

* feat: Removed 'isExternalType' function

* refactor: Decide if struct member takes ref or not when printing

..based on blitable interface, and 'prn' implemntation

* refactor: Use 'blit' everywhere

* refactor: Implement `strTakesRefOrNot` in terms of `memberStrCallingConvention`

* refactor: Use `remove` over `filter not`
2020-12-20 21:21:14 +01:00
Scott Olsen
5f0ae6819e
Various submodule fixes (#1078)
* fix: don't set the inner env to globals in type mods

Previously, we set the inner environment of a type generated module to
the global env in cases where the overarching context didn't have an
inner env. This leads to problems where by the recognition of modules is
inconsistent, and one can't use the names of types as submodules in
certain circumstances.

This commit fixes that issue.

* refactor: refactor primitiveDefmodule

This refactor fixes a issues with meta information on submodules, for
instance, sigs on submodule functions used to result in a compiler error
about ambiguous identifiers. This fixes that.

Unfortunately, I don't have a precise idea about what exactly was wrong
with the original definition of this function. My suspicion is that the
recursion originally altered submodule paths in the wrong way, but I'm
not certain. In any case it's fixed.

* fix: ensure macros are expanded in the correct module

Previously, macro expansions folded over all forms after the top level
form, without performing any context updates on encountered
`defmodules`. This created an issue in which macro calls that produced
new bindings, "meta stubs", were *hoisted* out of submodules and into
the top-level module, creating duplicate definitions.

This commit fixes that issue by adding a special case for defmodule in
macroExpand.

* fix: ensure submodules and globals don't conflict

Previously, our module lookups during new module definition always
eventually fell back to the global environment, which caused submodules
that happen to share a name with a global module to be confused with the
global module. This change fixes that, so now one can define both
`Dynamic` (global) and `Foo.Dynamic` without issue.

* fix: remove old prefixes from vector tests

Commit 7b7cb5d1e replaced /= with a generic function. However, the
vector tests still called the specific Vector variants of this function,
which were removed when the generic was introduced. After recent
changes, these calls are now (correctly) identified as erroneous. My
guess is that they only worked in the past because of problems with our
lookups.

* chore: format code
2020-12-18 21:45:28 +01:00
jacereda
b45b52b568
Add Dynamic.hash (#1069)
* feat: Add Dynamic.hash

* fix: Hash should be a Long
2020-12-16 15:53:55 +01:00
Scott Olsen
ee0aa59c28
Primitive refactors (#1070)
* refactor: move primitive errors; refactor primtiveInfo

This commit is the first in what will hopefully be a series of helpful
primitive refactors. To start, we:

- Move some inline `evalError` strings into a `PrimitiveError` module,
  (similar to the `TypeError`/`Types` module relationship
- Add `Reifiable` instances for String and Int types to take these
  types to their XObj representation.
- Add info utility functions for converting Info data to an XObj
- Refactor the `info` primitive:

  - Use monadic combinators + `maybe` instead of nested cases.
  - Use helper lookup functions that take a *context*--nearly *all*
    lookup calls currently extract some env, typically without doing
    anything to it, to pass it to lookup. This is a sign the boundary is
    incorrect and lookups should take the context instead--this will allow
    us to eliminate a ton of local `globalEnv`, `typeEnv`, etc. bindings.
  - Don't print hidden bindings
  - Indent printed meta information.
  - Color bindings blue

* chore: format code

* refactor: improve names for lookups that take a context

* feat: print hidden binders when calling info

Someone calling info might be interested in hidden binders as well, for
debugging purposes, etc. To enable this, we provide a version of show
for binders that prints hidden binders.

I've also made the printing of meta values in info more generic.
2020-12-15 21:38:55 +01:00
Veit Heller
629a6cf28d
load: allow for files to be loaded selectively (#1067) 2020-12-15 07:58:33 +01:00
jacereda
7814312c11
Add more variants for running external commands (#1066)
* feat: Implement run-with-args command

* feat: Implement run-exe-with-args command
2020-12-15 07:55:46 +01:00
Scott Olsen
321671c74a
fix: handle unhandled case in isCaptured (#1068)
Previously, this function missed a case, namely, one where the head of a
type definition contains a concrete struct, like `Maybe` with a variable
argument, `a`. That is,

```
(deftype (Foo (Maybe a)) [x (Maybe a)])
```

Would throw a type error. This commit fixes that issue.
2020-12-13 23:38:26 +01:00
jacereda
a0a3976441
Use different command types for each arity (#1063)
* refactor: Use different command types for each arity

* feat: Improved evaluation error messages in arity checks
2020-12-13 23:34:56 +01:00
jacereda
ccd9af500e
Address incomplete patterns (#1062)
* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Unused error

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Address incomplete patterns

* chore: Remove flag present only in newer ghc
2020-12-09 06:19:28 +01:00
Scott Olsen
8c5a117c82
fix: Handle unit members correctly in array templates (#1058)
* fix: Handle unit members correctly in array templates

Units may be used as members in arrays just like any other type,
however, the array templates (which are specific to arrays) hadn't been
updated to handle this. This commit makes the necessary updates and adds
some utility functions in efforts to make using templates in the
compiler easier.

After this commit, the following functions should work correctly on
(Array Unit):

- endo-map
- endo-filter
- copy
- aset!
- aset-uninitialized!
- aset
- pop-back!
- pop-back
- push-back
- push-back!

Just like other types with Unit members, the only value that is stored
in the resulting type is the terminal value of Unit `()` or unit. Any
side effects are run during evaluation of arguments and emitted prior to
any structure manipulations.

Because Unit is a terminal type (contains a single value) it makes
`endo-filter` an interesting case to consider. A filter on such an array
can only either retain all elements or drop all elements since there's
no way to predicate over the single terminal object Unit:

```
(endo-filter &(fn [_] false) [() ()])
=> []
(endo-filter &(fn [_] true) [() ()])
=> [() ()]
```

While arrays of units aren't very meaningful in terms of their contents,
their lengths will be expanded and contracted appropriately, so they can
be used for their length:

```
(defn iterate []
  (let-do [x [() () ()]]
    (while (> (Array.length &x) 0)
      (do (println* "foo")
          (Array.pop-back! &x)))))
(iterate)
Compiled to 'out/Untitled' (executable)
foo
foo
foo
=> 0
```

* chore: remove debugging trace

* refactor: make endo-filter template dryer
2020-12-08 17:29:55 +01:00
Veit Heller
45a5ce605f
feat: better error messages for invalid objects (#1056) 2020-12-07 12:29:33 +01:00
Scott Olsen
036be4a4dd
fix: ensure type variables kinds are consistent (#1055)
Previously, we didn't check that type variables had consistent kinds in
type definitions, which could lead to improper types. For example, one
could define:

    (deftype (Foo f a b) [x (f a) y f])

without issues even though this type is invalid since the variable `f`
is assigned two distinct kinds (nullary: * and unary: *->*).

This commit adds a check to ensure all of the instances of a type
variable in a type definition have the same kind. It also fixes an issue
whereby only higher-kinded types of one argument were allowed as type
members; now higher-kinded types of any arity are permitted (again
assuming variable kinds are consistent).

When a user writes a type that has variables with inconsistent kinds,
they will be hit with an error:

    (deftype (Foo (f a) b) [x (f a) y f])
    Invalid type definition for 'Foo':

    The type variable `f` is used inconsistently: (f a), f Type
    variables must be applied to the same number of arguments.

    Traceback:
    (deftype (Foo (f a) b) [x (f a) y f]) at REPL:1:1.
2020-12-07 10:09:39 +01:00
Erik Svedäng
b1aaa83b6a
refactor: Make Lookup module more focused and DRY (#1054)
* refactor: Move constraints test to own module, create TestLookup module

* refactor: Extracted 'Env' module

* refactor: Extracted 'TypePredicates' module

* test: First, very simple test

* refactor: Extracted 'Managed' module

* refactor: Add 'lookupBinder' function that doesn't return an Env (often what we want)

* refactor: Move out more stuff from Lookup

* refactor: Use new 'lookupBinder' in tons of places (avoids tuple)

* refactor: Got rid of monolithic 'recursiveLookupInternal'

* refactor: Avoid boolean blindness

* refactor: Better names for some lookup functions

* refactor: More logical order in Lookup.hs

* style: Use correct version of ormolu (0.1.4.1)

* refactor: Slightly more consistent naming

* refactor: Address @scolsen:s feedback
2020-12-07 07:06:32 +01:00
Scott Olsen
09fdd80f94
refactor: improve readability of interface functions (#1053)
* refactor: improve readability of interface functions

Also refactors the `define` function for readability.

The old definitions of these functions were quite unwieldy and difficult
to read. This refactor attempts to make the monadic contexts we're
juggling (often 3, Maybe, IO, Either) easier to spot.

* refactor: Add context env updaters; refactor prims

This commit contains a few more cleanups of the interface and define
functions in Primitives. It also defines a new context module for
holding functions that update context environments.
2020-12-05 21:00:28 +01:00
Erik Svedäng
696ea1a403 fix: Remove duplicated word in docstring 2020-12-05 13:26:27 +01:00
Erik Svedäng
a152a0d6e1
fix: Bumped Ormolu version to 0.1.4.1 (#1050) 2020-12-03 12:02:58 +01:00
Scott Olsen
88cffce626
fix: Filter unit types in a few more emissions (#1046)
There are a lot of different places that we need to filter Units out in
order to support them as type members, this commit catches a few more
cases that we missed:

- Lambda env captures
- Case matchers

Fixes issue #1044
2020-12-03 00:02:43 +01:00
Erik Svedäng
7920a751bf
refactor: Apply Ormolu auto-formatting (#1045) 2020-12-02 16:33:37 +01:00
jacereda
2a94f67db8
Address name shadowing (#1032)
* Rename ty to xobjTy.

* Rename info to xobjInfo.

* Rename obj to xobjObj.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Address name shadowing.

* Remove some primes.
2020-12-01 00:11:01 +01:00
Veit Heller
fe07a3f062
Refactor error reporting and add CARP_DIR check (#1033)
* compiler: refactor error reporting and add CARP_DIR check

Co-authored-by: Tim Dévé <TimDeve@users.noreply.github.com>

* set CARP_DIR in tests

Co-authored-by: Tim Dévé <TimDeve@users.noreply.github.com>
2020-11-30 15:58:25 +01:00
jacereda
ae2310b2c4
Fix #1001. (#1034) 2020-11-30 06:14:00 +01:00
jacereda
cb39a6a0c3
Address unused matches. (#1019) 2020-11-25 22:12:57 +01:00
jacereda
f6386c6b70
Address unused local bind. (#1018)
* Address unused local bind.

* Add TODO about possible bug.
2020-11-25 09:19:15 +01:00
Scott Olsen
eb85906e52
Meta set fix and refactor (#1008)
* Meta: Fix hangs on calls to meta functions

This commit fixes a subtle bug whereby setting the meta of an existing
binder would cause hangs. Ultimately, this still points to an underlying
issue in our Lookup code that causes such loops, but for now this at
least fixes the hang introduced by the doc call in `core/Tuples.carp`
(see issue #842).

The primary fix seems to be related to setting the parentEnv in a case
in which we failed to do so in `Eval.hs`. Additionally, our meta setting
macros call `eval` which causes them to be evaluated *immediately after*
expansion, causing them to be evaluated in the incorrect context in the
Tuples.carp case.

Additionally:

- Refactored primitiveMetaSet and primitiveMeta to make them cleaner.
- Only set `implements` early when we're certain we won't accidentally
  overwrite the interface.
- Generalize DocStub to `MetaStub` so that it may be used for forward
  meta declarations of any kind.

* Macros: Don't eval meta-set! macros

Calling eval in the body of the meta-set! macros can cause them to be
evaluated before anticipated, possibly setting the meta on a binding in
the incorrect environment. An exemplary case of this issue existed in
`Tuples.carp` (also fixed in this commit) whereby the generated
defmodule for a tuple type called doc, which was evaluated *before* the
emitted module, resulting in overwrites of global name docs instead of
the expected module function.

We retain `evals` in macros that are more useful in the repl, such as
`print-doc`. If a user wants to evaluated one of the meta-set macros in
the REPL, they'll need to add a call to eval.

* Macros: Restore calls to eval

Turns out the meta-set! macros *do* require calls to eval, unlike I
reported in the previous commit. This commit restores those and replaces
the `doc` call in `Tuples.carp` with a direct `meta-set!` to ensure we
have docs for those functions.

Also fixed a small error in implements primitive.

* Primitives: Refactor i->inner in primitiveImplements
2020-11-24 19:27:34 +01:00
jacereda
d742c24097
Compile with -Wall. (#1011)
* Prepare for -Wall.

* Address unused imports.

* Address missing signatures.

* Address unused do bind.

* Address type defaults.

* Address orphans.

* Switch to nixos-20.09.
2020-11-24 14:06:42 +01:00
jacereda
9520caf658
Replace return by pure. (#1009)
* Replace return by pure.

* Remove commandHelp again.
2020-11-24 06:09:15 +01:00
Erik Svedäng
48489a5771
feat: Implicit struct init (#1003)
* feat: Can omit .init in simple cases

* fix: Don't treat unqualified modules as interface sym:s

* feat: Can handle implicit init of type inside 'use':d module

* fix: Give deftypes and sumtypes correct parent environment!

* test: A few test cases

* refactor: Remove commented out code

Co-authored-by: Erik Svedang <erik@Eriks-iMac.local>
2020-11-23 09:59:35 +01:00
Erik Svedäng
793bf19ede
docs: Remove a lot of duplicated information and refer to webpages instead (#988)
* docs: Remove a lot of duplicated information and refer to webpages instead

* fix: Remove line about (help), it does not make sense anymore

* fix: Add open-browser to nix config

Co-authored-by: Erik Svedang <erik@Eriks-iMac.local>
2020-11-23 09:58:06 +01:00
Scott Olsen
8cc2ae1f2b
Eval: Add Address to eval (#1005)
The `address` keyword is useful when one needs to circumvent Carp's
memory management for particular cases. However, the evaluator
previously didn't understand `address` in most contexts, so it proved
difficult to toy around with in the REPL.

This commit adds basic support for calling `address` in the REPL by
adding a case to the evaluator. This allows users to test out functions
that take `Ptr` arguments such as `Pointer.to-value`. The `address`
keyword only accepts a symbol as an argument (since getting the address
of a literal value doesn't always make sense (e.g. &2) and produces
invalid C):

    (def a 1)
    (address a)
    => a
    (type (address a))
    => (Ptr Int)
    (Pointer.to-value (address a))
    => 1

Note: one will still typically need to wrap it in a function in
higher-order contexts.
2020-11-23 09:32:05 +01:00
jacereda
8e9f7bfd90
Split integer/floating point number representation. (#1006) 2020-11-23 06:28:30 +01:00
jacereda
244df27942
Unicode fixes (#994)
* Some compilers (tcc) will complain switching on const values.

* Fix unicode example when compiling with -std=c99.
2020-11-22 06:45:26 +01:00
jacereda
4065e09247
Cleanup double negations in unit detection. (#987) 2020-11-21 12:49:00 +01:00
Scott Olsen
c1e794c4cc
More Unit type member enhancements (#986)
* Emit/Deftype: Add a few more special cases for Unit members

There were a few gaps remaining in our handling of Unit types as members
of user defined types, most notably, generic setters weren't handling
Units appropriately. This commit adds special checks for Unit types in
generic setters, and also accounts for a Unit refs:

- Specialize generic setter functions against Unit members
- Specialize calls to str/prn against Unit members in StructUtils
  (rather than accessing the struct member, which doesn't exist in the
  Unit case, we simple call Unit's prn function (added in the next
  commit).
- Don't bind references to Unit values to variables. This fixes an error
  whereby a reference to a Unit would generate invalid C such as:
  `void* _9 = &;`
  Likewise, we omit references to Units from function arguments just as
  we omit Unit values.

* Unit: Add Unit type implementations for common interfaces.

Now that Unit can be used as a member type it is subject to several
interfaces, such as prn, that it previously hadn't implemented.

This commit adds Unit.carp to core which implements `prn`, `copy`, and
`zero` for the Unit type.

* Deftype: Return null pointers for Unit getters

This is *hopefully* one of the final updates needed to fully support
Unit's as member types. Getters for fields of such types have no struct
member to read, but are expected to return a void pointer; so we return
a NULL void pointer instead.

This commit also updates our emissions for function calls to prevent
assigning the results of functions with Unit and (Ref Unit) return types
to variables.

* Emit: Filter void args from lambda calls

Just as we filter void argument types from other function calls, we now
filter them from calls to lambdas.
2020-11-21 05:57:03 +01:00
scottolsen
a5ffb1b841 Reify: Add Unit as a special case
Unit's show implementation defaults to the empty list `()`--this
presents problems when validating types, since generic type members are
replaced by the reification (a type literal) of their arguments. In the
`Unit` case, `()` yields some surprising invalid types.

So, we reify UnitTy as `Unit` instead to ensure consistency. This
permits using  Unit as a member in generic types like Result.
2020-11-19 15:15:35 -05:00
Erik Svedäng
264d59b056
Merge pull request #910 from scolsen/construcible-refs
Allow Refs in polymorphic constructor positions
2020-11-17 22:25:07 +01:00
Erik Svedäng
c4b7dc3483
Merge pull request #967 from scolsen/unit-members
Allow Unit to be used as a member type in deftypes
2020-11-17 22:09:47 +01:00
scottolsen
912649dfeb Merge branch 'master' of https://github.com/carp-lang/Carp into fix-set-typing 2020-11-17 12:13:26 -05:00
scottolsen
5b0b18c2c2 InitialTypes: Add DefDynamic typing; make match exhaustive
Our initial type setting function didn't assign the Dynamic type to
DefDynamic forms; after this commit, it will. It also wasn't an
exhaustive match, leading to ugly non-exhaustive pattern match errors in
rare cases. This commit adds a clause to prevent that.
2020-11-17 12:11:44 -05:00
scottolsen
d5c56f8285 Eval,Obj: Add LetDef Obj and type check let bindings
This commit adds a new obj, `LetDef` which we use to give let bindings a
similar form to Def bindings and DefDynamic bindings. This enables us to
type check `set!` calls on let bindings just as we do def bindings and
defdynamic bindings.
2020-11-17 12:10:10 -05:00
Erik Svedang
9629195a62 fix: Remove noisy ouput when getting an unrecognized form in Eval 2020-11-16 20:26:37 +01:00
scottolsen
e2308ddc6e Restore initialization of dummy in deftypes 2020-11-16 02:10:54 -05:00
scottolsen
ee53585606 Add note about catchall case in setStaticOrDynamicVar 2020-11-16 01:41:56 -05:00
scottolsen
0735fb7af8 Merge branch 'master' of https://github.com/carp-lang/Carp into fix-set-typing 2020-11-16 01:38:18 -05:00
scottolsen
99f54680ff Fix instantiation of empty structs
Now that we properly omit all member fields for Unit types, the C
structs we instantiate cannot initialize *any* fields, rendering the
zero-initialization syntax invalid. We use an empty struct instead.
2020-11-16 01:32:24 -05:00
scottolsen
143fafc12a Allow Unit to be used as a member type in deftypes
This commit enables support for using values of type () (Unit) in
user-defined types such as product and sumtypes. After this commit,
types such as:

    (deftype Units [action-one () action-two ()])

Are valid, and can be instantiated in the obvious way:

    (Units.init (IO.println "foo") ())

Some important things to note about the implementation:

- The C structs emitted for types containing Unit members *completely
  omit all unit members*. If a type in Carp has N members, the
  corresponding C struct will have (N-U) members where U is the number of
  members with the type `Unit`.

  For example, this type:

    (deftype (Foo [one Unit two Int]))

  will produce the following typedef in C:

    typedef struct {
      int two;
    } Foo;

  As a special case, types that *only* have Unit's as members are represented and
  initialized as completely empty structs:

    (deftype Foo [empty Unit])

    // emits

    typedef struct {
    } Foo;

    Foo Foo_init() {
      Foo instance = {};

      return instance;
    }

   Such a type is merely a container for side effects.

- Side effects are not stored at all in the types that contain Unit
  members. Instead, any side effects will be lifted out of the emitted C
  struct and called prior to initialization.

  For example, initializing `(deftype Foo [empty Unit])` with `(Foo.init
  (IO.println "foo"))` will produce the following C:

    main(...) {
      //...
      static String _10 = "foo";
      String *_10_ref = &_10;
      IO_println(_10_ref);
      Foo _12 = Foo_init();
      //...
    }

- The typical operations on product fields are supported on Unit type
  members, but they have slightly custom semantics. Since we don't
  actually store any values of type Unit in custom types, most
  updaters/getters/setters simply run a side effect.

  This is mostly only supported to make the use of such members more
  intuitive and allow programmers to chain side-effects within some
  context, much like monadic IO in Haskell.

- Match forms also work on Unit types for parity, but again, there is no
  meaningful behavior here, since Unit only has a single type
  inhabitant.

As a bonus, this commit also makes it possible to use `Unit` and `()`
interchangeably in type signatures.
2020-11-16 01:06:44 -05:00
Erik Svedäng
a22551cd53 refactor: Use remove instead of filter + not 2020-11-11 07:05:12 +01:00
Erik Svedäng
fe9b07927a feat: Bring back the original (problematic) function 2020-11-11 06:58:41 +01:00
Erik Svedang
47dfd5900b fix: Make nameOfPolymorphicFunction not add so suffix to external functions 2020-11-10 23:14:26 +01:00
Erik Svedang
f9dadf335e fix: Avoid code duplication 2020-11-10 21:53:02 +01:00
Erik Svedang
6a8faddf7c fix: Compile shared library similarly to executable 2020-11-10 21:44:53 +01:00
Erik Svedäng
41687807fd
Merge pull request #953 from hellerve/veit/fix-use
Fix use when its not a symbol
2020-11-08 05:58:19 +01:00
hellerve
86b7f8b4f6 primitive: fix use when its not a symbol 2020-11-07 23:35:19 +01:00
hellerve
0f53c7da93 eval: catch static call error 2020-11-07 11:51:22 +01:00
hellerve
acce3a471c register-type: fix for void 2020-11-05 16:49:32 +01:00
Erik Svedäng
7d8b2d0f87
Merge pull request #941 from scolsen/expand-return
Eval: Make expand return the expanded form
2020-10-12 20:49:31 +02:00
Erik Svedäng
b5c375421f
Merge pull request #940 from scolsen/lookup-globals-first
Add flag to determine binding lookup preferences in the evaluator
2020-10-12 20:41:48 +02:00
scottolsen
3ed2eeca60 Eval: use a data type to indicate lookup preferences
This avoids boolean blindness and makes the semantics/purpose of the
lookup preference argument clearer.
2020-10-11 18:43:15 -04:00
scottolsen
841a35bcb5 Remove extraneous do notation + return from commandExpand 2020-10-10 22:15:24 -04:00
Jorge Acereda
58a61dd42e Add support for cross-compilation. 2020-10-10 20:01:18 +02:00
scottolsen
a3ada190dc Eval: Make expand return the expanded form
Previously, `expand` only printed the results of a macro expansion to
the console. However, there are legitimate use cases for having expand
return the expanded form, particularly, when nested macro calls should
be expanded but not evaluated. Consider the following:

```
(defmacro reff [] '(Ref Int <q>))

(defndynamic lt [x]
  (last x))

(defmacro wrapped [x] (lt x))
```

The above, when called with the `reff` macro as an argument, won't work
as expected, since macros don't evaluate their arguments:

```
(wrapped (reff))
=> reff
```

Currently, the solution is to wrap the `lt` argument in `eval`, but this
won't work, since even though it will expand the macro, it will try to
evaluate `Ref` after the expansion!

```
(defmacro wrapped [x] (lt (eval x)))

(wrapped (reff))
=> Can't find symbol 'Ref' at REPL:1:21.
```

Bummer. However, once we change expand to return a macro form instead of
echoing, we have a solution that allows us to expand a macro without
forcing an evaluation:

```
(defmacro wrapped [x] (lt (expand x)))

(wrapped (reff))
=> <q>
```

This allows programmers to define macros that can take expanded macros
as arguments. Because macros never evaluate their arguments, all calls
to `expand` need to be in the body of the wrapping macro to work:

```
(defmacro wrapped [x] (lt x))
(wrapped (expand (reff)))
=> (Ref Int <q>) ;; because:
;; (wrapped (expand (reff))) === (lt (expand (reff)))
;; (lt (expand (reff))) === (last (expand (reff)))
;; (last (expand (reff))) === (reff)
;; (reff) === (Ref Int <q>)
```

Expansion of values and symbols works as one might expect:

```
(expand 1)
=> 1
(expand \a)
=> \a
(expand "foo")
=> "foo"
(expand [])
=> []
...etc.
```

So, if a macro designer expects a macro to be used in combination with
some other macros, `expand` can typically be applied to all arguments
without penalty.
2020-10-09 17:35:42 -04:00
scottolsen
293956dac9 Eval: Add a flag for preferring dynamic/static bindings
In certain contexts, naked identifiers (those without a qualifying path)
can be resolved to either global static bindings *or* dynamic bindings.

In the past, we've always preferred dynamic bindings first in the
evaluator, then, if we failed to find them, fell back to global
bindings.

However, for the s-expr command for getting the s-expressions of
bindings, dynamic bindings can conflict with global bindings for
interfaces functions etc.

This commit makes it possible for callers into the dynamic evaluator to
specify whether they want to prioritize dynamic or global lookups. All
internal calls into eval from eval itself use whatever flag was passed
in at the top level. For parity, all existing calls to eval prefer
Dynamic bindings *except* for invocations of the s-expr command. That
acknowledged, we should revisit calls to eval and double check that the
lookup priorities make sense (for instance, primitives should likely
prefer dynamic bindings while identifiers in static terms like `defn`
bodies should prefer global/static bindings by default.
2020-10-07 18:41:55 -04:00
scottolsen
017fab0b91 Eval: Use Control typeclasses to organize lookups
This change reworks our code organization in the evaluator, moving from
explicit case statements on lookups to one that leverages
applicative/alternative and monadic structuring over lookup return
values.

Since lookups return Maybes, we can exploit these typeclasses to make
the code more modular. It's hopefully, much easier to switch the order
in which we perform binding lookups after this change, as we let the
alternative and bind implementations handle pattern matching over
structure for us.
2020-10-07 17:25:20 -04:00
Erik Svedäng
772051ede9
Merge pull request #939 from scolsen/reify
Enhance type reflection
2020-10-06 19:54:47 +02:00
scottolsen
4519b77161 Promote type's matching on types of Carp types
This is necessary to ensure we distinguish between the symbol "Type" as
returned by `type` from the type/module "Type" potentially defined by a
user:

```
(deftype Type)
(type Type)
=> Module
(type (type 1))
=> Type
;; Even though the symbol conflicts with the module defined above,
;; subsequent calls to type return the correct result.
(type (type (type 1)))
=> ()
```
2020-10-03 12:48:59 -04:00
scottolsen
25839de02d Enhance type reflection; get types of values, get kinds
Extends Carp's support for type reflection by returning types for
values as well as bindings.

`type` now also returns a valid Carp expression/s-expression and so its
output can be used as input to dynamic functions and macros (prior to
this commit, `type` printed the type to the REPL but did not return a
meaningful expression in Carp).

Here are a few illustrations of the behavior:

```
(def x 1)
;; type now returns an s-expression/symbol
(type x)
=> Int
;; It also works on values
(type 1)
=> Int
(type 2b)
=> Byte
(type "foo")
=> (Ref String <StaticLifetime>)
;; It works on more complex values as well
(type Maybe)
=> Module
(type Maybe.Just)
(Fn [a] (Maybe a) <StaticLifetime>)
;; reports honestly about polymorphism
(type (Maybe.Nothing))
=> (Maybe a)
(type (Pair.init 1 2))
=> (Pair Int Int)
;; What about the type of types?
(type (type 2))
=> Type
;; Or the type of types of types?
(type (type (type 2)))
=> ()
;; One more time!
(type (type (type (type 2))))
=> ()
;; so, () is the fixpoint of type, and is reached after two applications
(type zero)
;; the type of an interface is all of its implementations
=> (((Fn [] (Array a) <StaticLifetime>) (Fn [] Bool <StaticLifetime>) (Fn
[] Byte <StaticLifetime>) (Fn [] Char <StaticLifetime>) (Fn [] Double
<StaticLifetime>) (Fn [] Float <StaticLifetime>) (Fn [] Int
<StaticLifetime>) (Fn [] Int16 <StaticLifetime>) (Fn [] Int32
<StaticLifetime>) (Fn [] Int64 <StaticLifetime>) (Fn [] Int8
<StaticLifetime>) (Fn [] Long <StaticLifetime>) (Fn [] (Maybe a)
<StaticLifetime>) (Fn [] (Pair a b) <StaticLifetime>) (Fn [] (Quadruple
a b c d) <StaticLifetime>) (Fn [] String <StaticLifetime>) (Fn []
(Triple a b c) <StaticLifetime>) (Fn [] Uint16 <StaticLifetime>) (Fn []
Uint32 <StaticLifetime>) (Fn [] Uint64 <StaticLifetime>) (Fn [] Uint8
<StaticLifetime>)))
```

As shown in the example above, this change also includes a cosmetic
update to the representation of lifetime variables, which are surrounded
in <> to distinguish them from type variables.

This commit also adds a new `kind` primitive that reports on the kind of
a binding or value:

```
(def x 3)
(kind x)
=> Base
(kind 2)
=> Base
(kind Maybe.Just)
=> Higher
(kind (Maybe.Just 2))
=> Higher
```

`kind` and `type` both support interactive development in the repl, for
example, a user can rely on `kind` to check the kind of a type they plan
on using in an interface that demands a higher-kinded argument.

Likewise, they both also support developing macros based on type
information.
2020-10-02 17:48:58 -04:00
hellerve
309a8c2a23 commands: add length check to list and arry = 2020-10-02 18:38:53 +02:00
hellerve
be13979027 commands: expand comparables in = 2020-10-02 17:22:12 +02:00
scottolsen
0d43b492e5 Add DefDynamic to getPath
getPath returns the path of a form. The DefDynamic case was missing from
the function's definition, resulting in failures when calling functions
such as the meta set primitive on dynamic defs. This change fixes such
issues.
2020-10-01 16:46:53 -04:00
Erik Svedäng
ec20679440
Merge pull request #918 from hellerve/veit/static-args
core: use static array for args
2020-08-26 20:57:56 +02:00
Erik Svedäng
4dd61db153 Merge branch 'master' of https://github.com/carp-lang/Carp 2020-08-26 20:44:22 +02:00
scottolsen
4764fac56f Don't typecheck set! calls on local bindings
It turns out local binding XObjs and global binding XObjs have a very
different structure, making the type checking we perform on set! in
local contexts problematic.

While a global def resolves to a binding than contains: an XObj with the
bindings corresponding sympath and type

While a let binding's binder *only contains the bindings value*--so the
`x` in `let [x 2]` will resolve to an XObj only of `(Num Int....)`
instead of the more robust `(XObj Lst [SymPath....])` etc. This breaks
some assumptions of the set! type check, so until we make let bindings
and global bindings structurally equivalent, we won't type check `set!`s
on local bindings.
2020-08-25 13:10:29 -04:00
scottolsen
9525f74726 Refactor set! slightly; allow setting the global env locally
This change handles a case the previous implementation missed, that is,
when a user attempts to set a global variable in a local environment,
such as a let binding:

```
(def x 1)
(let [y 2] (set! x y))
(Int.+ 1 x)
=> 3
```

Internal definitions have precedence over globals, that is, if another
`x` in the let binding above shadowed the `x` in the global environment,
only the local `x` would be updated:

```
(def x 1)
(let [x 2] (set! x 3))
(Int.+ 1 x)
=> 2
```
2020-08-25 12:33:52 -04:00
hellerve
8ffaa908e5 eval: add comment about forcing trick in eval 2020-08-25 10:31:53 +02:00
hellerve
ef355b91d8 core: use static array for args 2020-08-24 11:20:52 +02:00
Scott Olsen
c397d9c758 Type check set! calls
This change enforces that `set!` calls do not change a variable's type.
Attempting to set a variable of type T to a value of type W will result
in an error. Dynamic variables are not type checked and may be set to
any value.

Generally speaking, it's safer to enforce this restriction on variables
for soundness reasons, and it's often the behavior programmers desire.
Additionally, this check resolves a problem whereby, previously,
reassigning a variable to a value of a different type and using it in
code thereafter would cause the compiler to hang.

Here's a brief illustration of the new behavior:

```
(def x 1)
(set! x "foo")
=> can't `set!` x to a value of type (Ref String a), x has type Int at
REPL:1:7.
(set! x 2)
(Int.+ 1 x)
=> 3
;; Dynamics can still be set to anything
(defdynamic y 2)
(set! y "foo")
:i y
(defdynamic y "foo") : Dynamic
;; Of course, one can still *redefine* a variable to change its type.
(set! x 3.4)
=> can't `set!` x to a value of type Double, x has type Int at REPL:1:7.
(def x 0.0)
[WARNING] Definition at line 1, column 1 in 'REPL' changed type of 'x'
from Int to Double
(set! x 10.0)
:i x
=> x : Double
```
2020-08-22 02:08:14 -04:00
Scott Olsen
266de6ac0f Ensure calls to set! remain well typed
Previously, we retyped *all* variables passed to `set!` as `DynamicTy`,
thus a variable set to a concrete type like `Int`, when `set!` would
suddenly have the type `Dynamic`. This change corrects that issue.
Variables are now typed according to the type of the value passed to
`set!`, and are only typed as Dynamic when the variable itself was
initially typed as `Dyanmic` (declared using defdynamic). To illustrate:

```
;; old behavior
(def x 1)
:i x
=> x : Int
(set! x 2)
:i x
=> x : Dynamic
;; new behavior
(def x 1)
:i x
=> x : Int
(set! x 2)
:i x
=> x : Int
(defdynamic y 2)
:i y
=> y : Dynamic
(set! y 3)
:i y
=>  y : Dynamic
```
2020-08-22 00:24:30 -04:00
Scott Olsen
f2e798cf9a Ensure command last calls handle empty lists
The `last` command relies on Haskell's `Prelude.last`--which will crash
on an empty list input. We report an error for incorrect input to last,
but we didn't handle the empty list case. This small change to our
pattern match ensures errors in carp code produce Carp's last command
error rather than causing `Prelude.last` to throw an error on empty list
input.
2020-08-21 17:58:39 -04:00
Jorge Acereda
fcef6af3f4 Fix Path docs. 2020-08-13 21:08:21 +02:00
scottolsen
14a3d9b5ab Support introspection on external functions
Like the previous two commits, this commit extends support for
reflection to yet another type, externally registered functions,
allowing us to support calls such as `(arity Int.+)`.
2020-08-10 17:56:28 -04:00
scottolsen
33a7f51c7b Support introspecting primitives
Just as the prior commit added support for capturing the arity of
registered commands, this one captures the arity of registered
primitives, enabling one to make calls such as `(arity defmacro)`, etc.

I have also moved the dummy argument name function into Util.hs since
it's used in both Commands.hs and Primitives.hs.
2020-08-10 17:06:46 -04:00
scottolsen
607d0c0664 Support introspection of commands
Previously, the command xobjs did not capture the arity of their
definitions. After this commit, they do, which enables us to surface
useful information about commands in reflective modules such as
core/Introspection.

Calls such as `(arity Dynamic.+)` and `(arity Dynamic.load)` will work
after this change.
2020-08-10 15:57:55 -04:00
Scott Olsen
69dea73425 Allow Refs in polymorphic constructor positions
This change makes refs "constructible" in the perspective of the type
system by allowing them to stand for polymorphic constructors such as
`(f a b)`. After this commit one can take an interface such as:

```
(definterface out (Fn [(f a b)] a))
```

and provide an implementation over references:

```
(defn copied [x] @x)
(implements out copied)
```

`copied` is a valid implementation of `out`, since it simply copies the
value of a reference, dropping its lifetime.

Essentially, this makes the type system slightly more flexible, allowing
one to view references as type constructors in their own right.
2020-08-08 01:24:04 -04:00
Erik Svedäng
0a2a2d257f
Merge pull request #894 from jacereda/addc
Added add-c to include additional compilation units in the compiler i…
2020-07-13 14:07:53 +02:00
Jorge Acereda
401dd36728 Revert submodules checkout changes. 2020-07-10 12:34:08 +02:00
Erik Svedäng
c61fce455f
Merge pull request #901 from scolsen/doc-gen
Honor project logo and url during module doc gen
2020-07-03 09:43:29 +02:00
Erik Svedäng
28873e92d0
Merge pull request #896 from hellerve/veit/unreachable
Add unreachable
2020-07-03 09:42:14 +02:00
Scott Olsen
0061d34338 Honor project logo and url during module doc gen
Previously, some of the documentation generations specific to Carp's
core library doc generation were hardcoded in renderdocs, thus, even
though users could set their own logo and url, these weren't honored
during the generation of module documentation, resulting in a bunch of
docs pointing to logos and urls that weren't intended.

This change updates the rendering code to honor the url and logo set in
the user's Project config.
2020-06-30 23:09:37 -04:00
Jorge Acereda
134d9a5b02 Implement load-stack. 2020-06-28 19:53:43 +02:00
Jorge Acereda
0d7533e887 Register additional modules in project. 2020-06-27 21:48:46 +02:00
hellerve
a96f774bc5 core: add unreachable 2020-06-23 12:19:14 +02:00
scottolsen
c5857c74c6 Add privacy checking to expansions
The previous commit added privacy checking to the evaluator--as it turns
out, this is only sufficient for top-level forms--interior forms, e.g.
forms in a `defn` are examined by `Expand` via `expandAll` and never
reach the `Eval` check.

To remedy this, I've added the check to symbol expansions. I've also
tweaked the signature of `expandSymbol` to align it with other functions
(e.g. `expandArray`).
2020-06-19 14:37:10 -04:00
scottolsen
b94b49bf86 Implement private
Even though `private?` has been around for a while, and we document the
behavior of `private` as marking a binding as private to a module--it
was never implemented as far as I can tell.

This implements private by adding a simple check to the evaluator. If a
binding is found in the global context, we check if it's marked as
private. If so, we inform the user that it can't be called from outside
of its module.

Note that we don't perform this check if the binding is found in the
internal env, since that means it's a function called within the same
module and thus is ok (even if marked as private).

After this change, something like the following works, granting us
proper encapsulation:

```
;; File Foo.carp
(deftype Foo [bar Int])

(private Foo.bar)

(defmodule Foo
  (defn get [foo]
    (Foo.bar foo))
)

;; Enter REPL
(load "Foo.carp")
(Foo.bar &(Foo.init 1))
The binding: Foo.bar is private; it may only be used within the module
that defines it. at REPL:1:2.
@(Foo.get &(Foo.init 1))
Compiled to 'out/Untitled' (executable)
1
=> 0
```

N.B. I also had to remove a private declaration from fmt-internal--this
declaration didn't really make much sense anyway, as fmt-internal is a
global function, so module-based privacy is not enforceable.
2020-06-19 10:30:55 -04:00
Erik Svedäng
753deaf0e6
Merge pull request #862 from Vertmo/fix-nesteddefn-eval
Generalization of the evaluation of static defn
2020-06-19 09:44:11 +02:00
Scott Olsen
ac5f88afd0 Merge branch 'master' of https://github.com/carp-lang/Carp into allow-interior-type-vars 2020-06-17 01:26:54 -04:00
Scott Olsen
8112ca04d3 Allow vars in polymorphic constructors to be members
Prior to this commit, a type such as: `(deftype (Foo (f a) [bar a]))`
was rejected by the compiler. However, such a type is sensible--Foo
ranges over some container type `f`, and it is essentially Foo's job to
provide a view into `f`, granting access to `a` and whisking `f` away
via the phantom constructor.

After this change, this type definition is now valid.

Note that one often needs to wrap phantom constructor cases in `the`
unless the type can be determined by the overarching context:

```
(deftype (Foo (f a) [bar a]))
(the (Foo (Maybe Int)) (Foo.init 1))
;; => (Foo 1)
```
2020-06-17 01:05:46 -04:00
Erik Svedäng
c7b926f259
Merge pull request #882 from TheAceShinigami/refactorPredicate
Refactor predicate
2020-06-16 20:09:32 +02:00
Erik Svedäng
b25cebc563
Merge pull request #880 from TheAceShinigami/master
include implemented functions in info
2020-06-16 20:08:56 +02:00
Erik Svedäng
3fffdd2f30
Merge pull request #883 from Vertmo/nested-lambdas-and-implicit-envs
Fixed lambda capture in presence of let bindings
2020-06-16 20:06:50 +02:00
Basile Pesin
94ce645b76 Added a descriptive comment for the new case in collectCapturedVars and removed duplicate code 2020-06-15 21:44:11 +02:00
Basile Pesin
dd6d3e9008 Fixed lambda capture in presence of let bindings 2020-06-15 21:44:11 +02:00
Basile Pesin
aa0a3e7ea9 Improved error message for HasStaticCall 2020-06-15 09:11:25 +02:00
thebarbershaveshimself
965f503cd0 extracted XObj predicates into Obj.hs 2020-06-14 16:31:17 -07:00
Jorge Acereda
1301531032 Return 0 from main when the return type is unit. 2020-06-14 23:32:36 +02:00
thebarbershaveshimself
b8433647f2 include implemented functions in info 2020-06-14 13:23:36 -07:00
Erik Svedäng
fc6d6aa626
Merge pull request #876 from leblowl/bug-843-fix
Attempt at fixing #843
2020-06-14 19:25:23 +02:00
Erik Svedäng
b1615648f2
Merge pull request #873 from TheAceShinigami/master
added error for malformed deftype
2020-06-14 19:23:44 +02:00
Lucas Leblow
fd89b64425 Attempt 2; only delete values, not refs 2020-06-13 18:05:37 -06:00
Lucas Leblow
5dd7c03a72 Attempt at fixing 843 2020-06-13 16:19:29 -06:00
thebarbershaveshimself
4547806f67 deleted useless comment 2020-06-13 12:25:39 -07:00
thebarbershaveshimself
8fb044c699 added error for malformed deftype 2020-06-13 12:07:20 -07:00
scottolsen
5955df79c8 Move interface registration functions into Interfaces.hs
This PR moves interface handling code out of Primitives.hs and into its
own module. The actual primitives user's rely on to define and implement
interfaces still live in Primitives.hs, but now all the
registration/internal context mgmt code related to interfaces lives in
its own module.

Hopefully this will make it easier to modify and extend!
2020-06-10 01:02:13 -04:00
scottolsen
131dca342d Refactor Primitives.hs functions
This change mostly just factors out case statements from a variety of
functions using two useful utilities `maybe` and `either`.

Essentially, these functions enable you to express a case against a
Maybe or Either in terms of a function and default value, and generally
help readability. In our case they:

- Allow us to remove tons of repetitive return statements.
- Allow us to remove do's.
- Eliminate some cases and simplify the code structure.

This commit contains no behavioral changes
2020-06-10 00:14:08 -04:00
scottolsen
1c1a29eea4 Refactor primitiveImplements 2020-06-09 16:51:38 -04:00
scottolsen
45f4ad5f07 Refactor primitive(File,Line,Column)
Using `maybe` makes many functions much shorter and hopefully more
manageable. Generally speaking, it allows us to remove case statements
over Maybes.
2020-06-09 15:45:28 -04:00
scottolsen
f6a854ef7b Replace Map manipulations on Meta with Meta module functions
This commit replaces instances that used `Data.Map` functions to
manipulate MetaData with their `Meta` module counterparts. In some cases
this allows us to drop the `Data.Map` dependency. In others, it's still
required since we take a similar approach for Envs--we should eventually
abstract away the underlying Map representation of `Env` too.
2020-06-09 15:00:49 -04:00
scottolsen
6ae3fc3008 Add Meta module
The Meta module does two things:

- Collects functions related to working with Carp MetaData in one place
- Hides the underlying implementation of MetaData
  MetaData is backed by `Data.Map` previously, we'd alter MetaData by
  getting the underlying map directly and calling Map functions to modify
  the contents. The functions in the Meta module encapsulate this--now
  callers may manipulate MetaData without having to know anything about
  the underlying Map implementation. This should make it easier to swap
  out the underlying representation in the future as well.
2020-06-09 14:28:07 -04:00
Erik Svedäng
7e440cae8c
Merge pull request #856 from jacereda/c99fixes
C99 fixes
2020-06-08 22:08:31 +02:00
Erik Svedäng
651c36f0d9
Merge pull request #859 from jacereda/pkgconfig-flags
Add pkgconfigflags.
2020-06-08 21:57:43 +02:00
Basile Pesin
72cc7bfca2 Evaluation for nested static calls 2020-06-07 00:22:39 +02:00
scottolsen
f3aa543fe0 Add a note about issue #521 2020-06-03 11:16:10 -04:00
scottolsen
ff0596ebab Restore tyvar check in constraints; special case interface
Previously, I'd removed the type var check in constraint conflict
checking. This doesn't seem to be problematic, but it might not be the
best way to implement the desired result, which is special conflict
checking for interfaces.

This approach is more conservative and simply bypasses the check for
interface implementation constraint solving only.
2020-06-02 10:54:09 -04:00
Scott Olsen
f062e054dd Merge branch 'master' of https://github.com/carp-lang/Carp into constrained-interfaces 2020-06-02 00:46:00 -04:00
Scott Olsen
7dbb4dd400 Replace conflicting vars with special names 2020-06-02 00:40:49 -04:00
Scott Olsen
94adcc1b30 Allow unification of type vars using the same name
Previously we disallowed unification of type variables with types that
contained the same variable name; e.g. unification of `a` with `(Ref
a)` was disallowed by the type system.

While this was a pain for defining custom struct types, it becomes even
more problematic after the past commit, as, since interfaces now solve a
constraint, it means a n interface (a -> a) cannot be unified with an
implementation ((Ref a) -> (Ref a)).

As it turns out, simply removing this rule causes no evident breakages
or problems, and makes the newly constrained and type rigorous interface
matching more ergonomic to work with in addition to removing the custom
struct definition annoyances.
2020-06-01 23:33:11 -04:00
Scott Olsen
9f5f99a696 Solve for constraints when matching interfaces
Previously, we only checked that interface signatures and implementation
signatures were unifiable. This check is actually not sufficient, and
leads to interface typings that are overly permissive. For example, the
interface (a -> a) unifies with everything, even an implementation typed
(Int -> Double) which is patently incorrect.

Solving a basic constraint between the interface an implementation fixes
this issue.
2020-06-01 23:29:42 -04:00
Scott Olsen
7b2991bb0d Allow "Instantiate" functions to implement interfaces
This change makes it possible to declare auto-derived getter/setter
functions on types as implementations of interfaces, e.g. Pair.a.

The same checks for normal functions apply to the instantiations. For
example, given an interface:

```
(definterface left (Fn [(Ref (f a b))] (Ref a)))
```

`Pair.a` can implement this interface, but `Maybe.Just` cannot--since it
results in a kind mismatch.

I also realized that interfaces are currently too flexible/permissive.
For example, given an interface:

```
(definterface id (Fn [a] a))
```

Most, if not all, functions can implement this interface, even when the
implementation clearly doesn't conform. For example, `Pair.a` or even a
function with the type `([String] Int)` are both valid implementations
of this interface. This is because we currently only check if interfaces
and implementation signatures are unifiable. Since we consider any type
unifiable with a variable, any implementation passes, even when the
argument type and return type are clearly not the same. We'll need to
constraint solve on the interface and implementation signatures to fix
this--since that's a more significant change, it's omitted from this PR.
For now a new TODO will have to suffice.
2020-06-01 20:41:54 -04:00
Jorge Acereda
6656d96791 Add pkgconfigflags. 2020-06-01 21:34:12 +02:00
Erik Svedäng
8715502e05
Merge pull request #850 from Vertmo/fix-nestedlambdas-capture
Fixed the issue with nested capture and nested lambdas
2020-06-01 21:10:14 +02:00
Jorge Acereda
121e3fa56d C99 fixes 2020-05-30 22:37:01 +02:00
Jorge Acereda
543a90ffa0 Add joinLines. 2020-05-30 09:19:26 +02:00
Basile Pesin
4ab29d84ac Fixed the issue with nested capture and nested lambdas 2020-05-28 20:05:27 +02:00
scottolsen
e1a7c3149a Return an error instead of () on invalid s-expressions
`s-expr` accepts either a binding that evaluates to a List or a list
literal such as `'(1 2 3)`. Other forms do not yield s-expressions, and
so we return an error. For example, `(s-expr '[1 2])` returns an error
since an array does not form a list s-expression.
2020-05-27 16:04:34 -04:00
scottolsen
96a9dcf95b Make Sexpression a command, enhance module introspection
Originally, s-expr was a primitive and didn't evaluate its arguments.
This however make it difficult to use, in addition to forcing us to make
an extra unnecessary lookup. This commit converts s-expr to a command,
which makes it a lot simpler to use in macro definitions and in dynamic
code in general.

Additionally, I've enhanced it to do two things:

- Allow users to get the module for a type instead of the definition
  form using an optional argument.
- List the contents of a module upon getting its s-expr.

Many thanks to @hellerve who both suggested this change and advised.
2020-05-27 13:30:35 -04:00
hellerve
0959538d00 parser: add base16 and base2 literals 2020-05-27 11:45:29 +02:00
Erik Svedäng
7a393d38d3
Merge pull request #838 from scolsen/s-epr-interfaces
Improve introspection support for interfaces
2020-05-26 20:44:55 +02:00
Erik Svedäng
4c4bf56c5c
Merge pull request #844 from sdilts/register-type-doc
Improve register-type documentation
2020-05-26 20:34:18 +02:00
hellerve
1d7ef556f2 eval: make ref literals work in the repl 2020-05-26 11:11:27 +02:00
sdilts
f26738ef4e Improve register-type documentation
Add info about specifying c names in the `register-type` docstring
2020-05-25 12:38:52 -06:00
Scott Olsen
9b9aa76b59 Improve introspection support for interfaces
Previously, introspecting an interface only returned `definterface` and
its name. We now return the form corresponding to the interface's types
signature, which enables us to introspect more effectively; e.g.
returning the appropriate arity of an interface.
2020-05-24 17:02:35 -04:00
Erik Svedäng
69ffac4097
Merge pull request #832 from Vertmo/cleanup-types
Separated Types utilities into SymPath.hs and TypesToC.hs
2020-05-24 11:49:14 +02:00
Erik Svedäng
ea372b1728
Merge pull request #827 from jacereda/cmdline-eval
Command line switches to evaluate code
2020-05-24 11:45:44 +02:00
Basile Pesin
8de9a416cb Separated Types utilities into SymPath.hs and TypesToC.hs 2020-05-24 11:08:17 +02:00