59 Commits 253f2bc301 ... 46e3fd3048

Author SHA1 Message Date
  mizusato 46e3fd3048 argv, envp 1 year ago
  mizusato 81dfb6d63f update todos 1 year ago
  mizusato b61bb89a34 adjust 1 year ago
  mizusato 4c63bacc99 slider, progress bar 1 year ago
  mizusato 602a13f677 add todos 1 year ago
  mizusato 75159cb26f adjust 1 year ago
  mizusato c415edf971 fix 1 year ago
  mizusato d5ea3c8b46 fix 1 year ago
  mizusato e773aea698 load dependency 1 year ago
  mizusato db6aa68f53 unused binding error 1 year ago
  mizusato d78d9f35f4 fix 1 year ago
  mizusato 13dd6f0e06 update todos 1 year ago
  mizusato 163c6cb83e cached expr 1 year ago
  mizusato bfad438b09 adjust 1 year ago
  mizusato 0b3ce564cb add todo 1 year ago
  mizusato e9ceb92d06 fix 1 year ago
  mizusato bc53e7ea5c remove obsolete code 1 year ago
  mizusato 4de018cf45 update todos 1 year ago
  mizusato 291f5c558b repl cmd history 1 year ago
  mizusato dd72bac93f fix 1 year ago
  mizusato a542648ead revert 1 year ago
  mizusato f3a0c54226 input popup 1 year ago
  mizusato 04bdc846d7 adjust 1 year ago
  mizusato 0f9c3e96ed adjust 1 year ago
  mizusato 2606bba693 adjust 1 year ago
  mizusato 81ca9bd2a5 indent, unindent 1 year ago
  mizusato 09497ff89f fix, adjust 1 year ago
  mizusato 74faf10a26 linter tooltip, adjust 1 year ago
  mizusato 15a75f2b15 wave underline, adjust 1 year ago
  mizusato 0f5d47ccb7 linter 1 year ago
  mizusato 1873151318 node cut ad hoc impl 1 year ago
  mizusato a9b2b14e1d fix for windows 1 year ago
  mizusato 5a3c7b041b adjust 1 year ago
  mizusato 20e532c253 edit selection 1 year ago
  mizusato 8c1ca4f01d adjust 1 year ago
  mizusato 7d7ee1c664 right click, adjust 1 year ago
  mizusato 0e49df617e center cursor x 1 year ago
  mizusato 960cf2916d step in, step out 1 year ago
  mizusato 7208da2c67 step back 1 year ago
  mizusato e910079f38 fix 1 year ago
  mizusato 49ec97707c fix 1 year ago
  mizusato 8c56e6edc9 refactor 1 year ago
  mizusato e555a3c61a step over ad hoc impl 1 year ago
  mizusato 0011a4af31 highlight focus, adjust 1 year ago
  mizusato bf052a6aa5 update todos 1 year ago
  mizusato ab83242f1b window activate event 1 year ago
  mizusato 84eeebf973 disable drag 1 year ago
  mizusato fa607b853f better highlight, fix 1 year ago
  mizusato a280139bc7 fix 1 year ago
  mizusato a52a9b5665 adjust 1 year ago
  mizusato c3d70a2f64 select all 1 year ago
  mizusato 122a38e31b fix 1 year ago
  mizusato f59a82144e adjust 1 year ago
  mizusato 8bce58bb29 undo, redo 1 year ago
  mizusato af047585fc cut, copy, paste 1 year ago
  mizusato 5f38808a90 fix 1 year ago
  mizusato abafb83025 highlight, refactor index, adjust 1 year ago
  mizusato b7e37f3b51 fix 1 year ago
  mizusato 826ab6dc96 fix, add todos 1 year ago

+ 1 - 0
.idea/dictionaries/mizusato.xml

@@ -71,6 +71,7 @@
       <w>ufcs</w>
       <w>unbox</w>
       <w>unboxes</w>
+      <w>unindent</w>
       <w>unpop</w>
       <w>unpopped</w>
       <w>unshifted</w>

+ 20 - 49
TODO

@@ -2,59 +2,35 @@ TODO
 
 ## Important
 
-IDE
-    - browser-like navigation: back, forward, recent history
-    - undocumented type/field/func/... /^(<.+>).*$/
-
-lang
-    - cached expression (only need to be evaluated once)
-        - const
-        - const_binding: { const foo = (mask local scope), return }
-            - mask local scope: create new ctx, only preserve const bindings
-            - use it in json example
-
-compiler
-    - unused binding check on when/each expr, lambda
-    - load dependency projects
-
-filesystem API:
-    - debugger log
+file dialogs:
     - opaque File(path) type
-        - CacheFile(name), ConfigFile(name)
-    - sanitize file name
-    - read/write whole file (Object/Text) record { V1 Maybe[V1], V2 ... }
-        - ReadAssetFile(rel_path)
-    - open/save file using dialog
-    - get selected folder path using dialog
-    - get selected file path(s) using dialog
 
-http API:
+I/O API:
     - debugger log
     - json restful client
+        - http(s)://
+        - stdio://
         - access token in header
-        - Request(enum { Get, Post, Put, Delete })
-        - TextRequest
-        - Subscribe (chunked transfer encoding)
-        - Download (with progress)
-        - Upload (with progress)
-
-exec API:
-    - debugger log
-    - companion program (pipe server)
-        - CompanionRequest (cancellable)
-        - CompanionSubscribe
-    - ExecReadAllText
-    - ExecReadLines
-    - ExecDetached
-    - Error.ExitCode
+        - Get, Post, Put, Delete
+        - Subscribe (stdio only)
+    - stdio: func StartCoproc(); add stdin/stdout params to CompileAndRun
+    - consider: exec in terminal
 
 BoxLayoutListWidget
     - don't inherit SmartScrollArea: fit content, use external scroll area
     - RowEditView, ColumnEditView
 
-Slider, ProgressBar
+adjust
+    - revise names like '<Foo>BarBaz'
+    - prop/signal name(signature) should be string CONSTANT in the qt package
+    - no Error() dummy method (-> ctn.StableSorted, program.Cached)
+    - qtbinding C side int vs. go side int (clamp to int32)
+
+docs
+    - doc gen
+    - index gen (autocomplete uses a pre-generated builtin symbol index)
 
-Wizard
+# Postponed
 
 Canvas
     - use Action instead of listening to key event directly on Window
@@ -65,13 +41,8 @@ Canvas
     - $[Pair[CanvasMouseEvent,T]]
     - canvas bind-refresh ($[CanvasContent[T]]) // bind-render (capacity=1)
 
-MdiArea, StaticTabs, DockWindow, SystemTrayIcon
+Wizard, MdiArea, StaticTabs, DockWindow, SystemTrayIcon
 
-adjust
-    - revise names like '<Foo>BarBaz'
-    - prop/signal name(signature) should be string CONSTANT in the qt package
-    - qtbinding util function UnwrapIcon(), UnwrapFoo(), UnwrapBar(), ...
-    - no Error() dummy method
-    - qtbinding C side int vs. go side int (not the same type, fix it)
+DateTime API, TimeEdit, DateEdit, DateTimeEdit, CalendarWidget
 
 

+ 39 - 8
interpreter/builtin/builtin.km

@@ -428,9 +428,12 @@ operator compose[A,B,C] { ab Lens2[A,B], f Lambda[Maybe[B],Lens2[B,C]] } Lens2[A
 
 function ApiGet[T] { endpoint String, t IntoReflectType[T] } $[T] native('ApiGet')
 
-const BaseFontSize Int native('BaseFontSize')
+const Arguments List[String] native('Arguments')
+const Environment List[String] native('Environment')
 
-function ShowInfo     { content String, title String('Information') } $[None] native('ShowInfo')
+const FontSize Int native('FontSize')
+
+function ShowInfo     { content String, title String('Info') } $[None] native('ShowInfo')
 function ShowWarning  { content String, title String('Warning') } $[None] native('ShowWarning')
 function ShowCritical { content String, title String('Error') } $[None] native('ShowCritical')
 function ShowYesNo             { content String, title String('Question') } $[Bool] native('ShowYesNo')
@@ -492,14 +495,16 @@ function <Widget>CreateSplitter { l List[Widget] } Hook[Widget] native('WidgetCr
 function <Widget>CreateMainWindow { menu-bar MenuBar, tool-bar ToolBar, l Layout, margin-x Int, margin-y Int, width Int, height Int, icon Icon } Hook[Widget] native('WidgetCreateMainWindow')
 function <Widget>CreateDialog { l Layout, margin-x Int, margin-y Int, width Int, height Int, icon Icon } Hook[Widget] native('WidgetCreateDialog')
 function <Widget>CreateLabel { align Align, selectable Bool } Hook[Widget] native('WidgetCreateLabel')
-function <Widget>CreateIconLabel { icon Icon } Hook[Widget] native('WidgetCreateIconLabel')
+function <Widget>CreateIconLabel { icon Icon, size Int } Hook[Widget] native('WidgetCreateIconLabel')
 function <Widget>CreateElidedLabel {} Hook[Widget] native('WidgetCreateElidedLabel')
 function <Widget>CreateTextView { format TextFormat } Hook[Widget] native('WidgetCreateTextView')
 function <Widget>CreateCheckBox { text String, checked Bool } Hook[Widget] native('WidgetCreateCheckBox')
 function <Widget>CreateComboBox[T] { items List[ComboBoxItem[T]] } Hook[Widget] native('WidgetCreateComboBox')
 function <Widget>CreatePushButton { icon Icon, text String, tooltip String } Hook[Widget] native('WidgetCreatePushButton')
 function <Widget>CreateLineEdit { text String } Hook[Widget] native('WidgetCreateLineEdit')
-function <Widget>CreateDummyFocusableWidget {} Hook[Widget] native('WidgetCreateDummyFocusableWidget')
+function <Widget>CreatePlainTextEdit { text String } Hook[Widget] native('WidgetCreatePlainTextEdit')
+function <Widget>CreateSlider { value Int, min Int, max Int } Hook[Widget] native('WidgetCreateSlider')
+function <Widget>CreateProgressBar { max Int, format String } Hook[Widget] native('WidgetCreateProgressBar')
 
 type <Signal>[T] native
 type <Events>[T] native
@@ -507,9 +512,11 @@ function <Connect>[T] { s <Signal>[T], w Widget } $[T] native('Connect')
 function <Listen>[T]  { s <Events>[T], w Widget } $[T] native('Listen')
 const <Signal>Toggled <Signal>[None] native('SignalToggled')
 const <Signal>Clicked <Signal>[None] native('SignalClicked')
-const <Signal>TextChanged <Signal>[None] native('SignalTextChanged')
+const <Signal>TextChanged0 <Signal>[None] native('SignalTextChanged0')
+const <Signal>TextChanged1 <Signal>[None] native('SignalTextChanged1')
 const <Signal>ReturnPressed <Signal>[None] native('SignalReturnPressed')
 const <Signal>Rejected <Signal>[None] native('SignalRejected')
+const <Signal>ValueChanged <Signal>[None] native('SignalValueChanged')
 const <Events>Close <Events>[None] native('EventsClose')
 
 type <Prop>[T] native
@@ -520,6 +527,8 @@ const <Prop>Enabled <Prop>[Bool] native('PropEnabled')
 const <Prop>WindowTitle <Prop>[String] native('PropWindowTitle')
 const <Prop>Text <Prop>[String] native('PropText')
 const <Prop>Checked <Prop>[Bool] native('PropChecked')
+const <Prop>PlainText <Prop>[String] native('PropPlainText')
+const <Prop>Value <Prop>[Int] native('PropValue')
 
 type Icon record { Name String }
 function Icon { name String('') } Icon { new Icon(name) }
@@ -617,10 +626,11 @@ function ElidedLabel { text $[String] } Hook[ElidedLabel] {
 }
 
 type IconLabel record { Widget Widget }
-function IconLabel { icon Icon } Hook[IconLabel] {
-    @use widget = <Widget>CreateIconLabel(icon),
+function IconLabel { icon Icon, size IconSize(Auto) } Hook[IconLabel] {
+    @use widget = <Widget>CreateIconLabel(icon, ([Int])size),
     Hook(new IconLabel(widget))
 }
+type IconSize enum { Auto, Small, Medium, Large }
 
 type TextView record { Widget Widget }
 function TextView { text $[String], format TextFormat(Plain) } Hook[TextView] {
@@ -666,12 +676,33 @@ function TextBox { text String('') } Hook[TextBox] {
     @use widget = <Widget>CreateLineEdit(text),
     Hook(new TextBox(widget))
 }
-method TextBox.Text $[String] { <Connect>(<Read>(<Prop>Text, <Signal>TextChanged), this.Widget) }
+method TextBox.Text $[String] { <Connect>(<Read>(<Prop>Text, <Signal>TextChanged1), this.Widget) }
 method TextBox.Enter $[None] { <Connect>(<Signal>ReturnPressed, this.Widget) }
 method TextBox.TextOn Lambda[$[None],$[String]] {{ triggers => <ClearTextLater>(this.Widget, (triggers map-to-latest-from this.Text)) }}
 method TextBox.TextOnEnter $[String] { this.TextOn(this.Enter) }
 operator bind-override { edit TextBox, text $[String] } $[None] { <Bind>(<Prop>Text, text, edit.Widget) }
 
+type TextArea record { Widget Widget }
+function TextArea { text String('') } Hook[TextArea] {
+    @use widget = <Widget>CreatePlainTextEdit(text),
+    Hook(new TextArea(widget))
+}
+method TextArea.Text $[String] { <Connect>(<Read>(<Prop>PlainText, <Signal>TextChanged0), this.Widget) }
+
+type Slider record { Widget Widget }
+function Slider { value Int, min Int, max Int } Hook[Slider] {
+    @use widget = <Widget>CreateSlider(value, min, max),
+    Hook(new Slider(widget))
+}
+method Slider.Value $[Int] { <Connect>(<Read>(<Prop>Value, <Signal>ValueChanged), this.Widget) }
+
+type ProgressBar record { Widget Widget }
+function ProgressBar { value $[Int], max Int, format String('') } Hook[ProgressBar] {
+    @use widget = <Widget>CreateProgressBar(max, format),
+    @use Effect(<Bind>(<Prop>Value, value, widget)),
+    Hook(new ProgressBar(widget))
+}
+
 type ListView[T] record {
     Widget    Widget,
     Extension $[Maybe[Widget]],

+ 50 - 11
interpreter/builtin/builtin2.go

@@ -2,6 +2,7 @@ package builtin
 
 import (
 	"io"
+	"os"
 	"fmt"
 	"math"
 	"time"
@@ -137,11 +138,14 @@ var functionList = [] interface{} {
 	core.Multicast, core.Loopback, core.SkipSync,
 	// Time
 	TimeString, TimeSubtractMillisecond,
-	// Network
+	// Request
 	ApiGet,
+	// Process
+	Arguments,
+	Environment,
 	// GUI
 	// general
-	BaseFontSize,
+	FontSize,
 	// standard dialogs
 	ShowInfo, ShowWarning, ShowCritical,
 	ShowYesNo, ShowAbortRetryIgnore, ShowSaveDiscardCancel,
@@ -168,14 +172,18 @@ var functionList = [] interface{} {
 	WidgetCreateComboBox,
 	WidgetCreatePushButton,
 	WidgetCreateLineEdit,
-	WidgetCreateDummyFocusableWidget,
+	WidgetCreatePlainTextEdit,
+	WidgetCreateSlider,
+	WidgetCreateProgressBar,
 	// signal and events
 	Connect, Listen,
 	SignalToggled,
 	SignalClicked,
-	SignalTextChanged,
+	SignalTextChanged0,
+	SignalTextChanged1,
 	SignalReturnPressed,
 	SignalRejected,
+	SignalValueChanged,
 	EventsClose,
 	// prop
 	Read,
@@ -185,6 +193,8 @@ var functionList = [] interface{} {
 	PropWindowTitle,
 	PropText,
 	PropChecked,
+	PropPlainText,
+	PropValue,
 	// advanced
 	Switchable,
 	Reloadable,
@@ -1157,8 +1167,15 @@ func ApiGet(endpoint string, rt core.ReflectType, h core.RuntimeHandle) core.Obs
 	})
 }
 
-func BaseFontSize() int {
-	return qt.BaseFontSize()
+func Arguments(h core.RuntimeHandle) ([] string) {
+	return h.ProgramArgs()
+}
+func Environment() ([] string) {
+	return os.Environ()
+}
+
+func FontSize() int {
+	return qt.FontSize()
 }
 
 func ShowInfo(content string, title string) core.Observable {
@@ -1475,9 +1492,9 @@ func WidgetCreateLabel(align Align, selectable bool) core.Hook {
 		return qt.CreateLabel("", convertAlign(align), selectable, ctx).Widget
 	})
 }
-func WidgetCreateIconLabel(icon Icon, h core.RuntimeHandle) core.Hook {
+func WidgetCreateIconLabel(icon Icon, size int, h core.RuntimeHandle) core.Hook {
 	return createWidget(func(ctx qt.Pkg) qt.Widget {
-		return qt.CreateIconLabel(convertIcon(icon, h), ctx).Widget
+		return qt.CreateIconLabel(convertIcon(icon, h), size, ctx).Widget
 	})
 }
 func WidgetCreateElidedLabel() core.Hook {
@@ -1516,9 +1533,19 @@ func WidgetCreateLineEdit(text string) core.Hook {
 		return qt.CreateLineEdit(text, ctx).Widget
 	})
 }
-func WidgetCreateDummyFocusableWidget() core.Hook {
+func WidgetCreatePlainTextEdit(text string) core.Hook {
 	return createWidget(func(ctx qt.Pkg) qt.Widget {
-		return qt.CreateDummyFocusableWidget(ctx).Widget
+		return qt.CreatePlainTextEdit(text, ctx).Widget
+	})
+}
+func WidgetCreateSlider(value int, min int, max int) core.Hook {
+	return createWidget(func(ctx qt.Pkg) qt.Widget {
+		return qt.CreateSlider(min, max, value, ctx).Widget
+	})
+}
+func WidgetCreateProgressBar(max int, format string) core.Hook {
+	return createWidget(func(ctx qt.Pkg) qt.Widget {
+		return qt.CreateProgressBar(format, max, ctx).Widget
 	})
 }
 
@@ -1534,7 +1561,10 @@ func SignalToggled() core.Signal {
 func SignalClicked() core.Signal {
 	return core.MakeSignal("clicked(bool)")
 }
-func SignalTextChanged() core.Signal {
+func SignalTextChanged0() core.Signal {
+	return core.MakeSignal("textChanged()")
+}
+func SignalTextChanged1() core.Signal {
 	return core.MakeSignal("textChanged(const QString&)")
 }
 func SignalReturnPressed() core.Signal {
@@ -1543,6 +1573,9 @@ func SignalReturnPressed() core.Signal {
 func SignalRejected() core.Signal {
 	return core.MakeSignal("rejected()")
 }
+func SignalValueChanged() core.Signal {
+	return core.MakeSignal("valueChanged(int)")
+}
 func EventsClose() core.Events {
 	return core.MakeEvents(qt.EventClose(), true)
 }
@@ -1575,6 +1608,12 @@ func PropText() core.Prop {
 func PropChecked() core.Prop {
 	return core.MakeProp(core.PropBool, "checked")
 }
+func PropPlainText() core.Prop {
+	return core.MakeProp(core.PropString, "plainText")
+}
+func PropValue() core.Prop {
+	return core.MakeProp(core.PropInt, "value")
+}
 
 type Switchable_T struct {
 	Widget  core.Widget

+ 13 - 8
interpreter/compiler/compiler.go

@@ -19,31 +19,34 @@ type DebugInfo struct {
 }
 
 func Compile(groups ([] SourceFileGroup), meta program.Metadata) (*program.Program, *DebugInfo, richtext.Errors, source.Errors) {
-	var ldr_errs = new(richtext.Errors)
-	var chk_errs = new(source.Errors)
+	var ldr_errs richtext.Errors
+	var chk_errs source.Errors
 	var hdr_list = make([] *Header, 0)
 	var impl_list = make([] *Impl, 0)
 	for _, group := range groups {
 		for _, file := range group.FileList {
 			var root, err = Load(file, group.FileSystem)
 			if err == nil {
-				var hdr, impl = analyze(root, chk_errs)
+				var hdr, impl = analyze(root, &chk_errs)
 				hdr_list = append(hdr_list, hdr)
 				impl_list = append(impl_list, impl)
 			} else {
-				richtext.ErrorsJoin(ldr_errs, err)
+				richtext.ErrorsJoin(&ldr_errs, err)
 			}
 		}
 	}
-	var ctx = groupHeaders(hdr_list, chk_errs)
+	if ldr_errs != nil {
+		return nil, nil, ldr_errs, chk_errs
+	}
+	var ctx = groupHeaders(hdr_list, &chk_errs)
 	var fragments = make([] *Fragment, 0)
 	for _, hdr := range hdr_list {
-		checkHeader(hdr, ctx, chk_errs)
+		checkHeader(hdr, ctx, &chk_errs)
 	}
 	for i := range hdr_list {
 		var hdr = hdr_list[i]
 		var impl = impl_list[i]
-		var fragment = compileImpl(impl, hdr, ctx, chk_errs)
+		var fragment = compileImpl(impl, hdr, ctx, &chk_errs)
 		fragments = append(fragments, fragment)
 	}
 	var rtti = ctx.generateTypeInfo()
@@ -57,7 +60,7 @@ func Compile(groups ([] SourceFileGroup), meta program.Metadata) (*program.Progr
 		Context:    ctx,
 		Executable: exe,
 	}
-	return p, info, *ldr_errs, *chk_errs
+	return p, info, ldr_errs, chk_errs
 }
 
 func CompileExpr(node ast.Expr, ns string, expected typsys.Type, bindings ([] *program.Binding), info *DebugInfo) (*program.Expr, *source.Error) {
@@ -65,10 +68,12 @@ func CompileExpr(node ast.Expr, ns string, expected typsys.Type, bindings ([] *p
 	var ec = createExprContext(nil, fd, info.Context)
 	for _, b := range bindings {
 		ec.addBinding(b)
+		ec.useBinding(b.Name)
 	}
 	var cc = createExprCheckContext(expected, ec)
 	var expr, err = checkExpr(node, cc)
 	if err != nil { return nil, err }
+	if err := ec.unusedBindingError(); err != nil { return nil, err }
 	var fragment = fd.content
 	linkFragment(info.Executable, fragment)
 	return expr, nil

+ 28 - 11
interpreter/compiler/errors.go

@@ -314,7 +314,17 @@ type E_DuplicateBinding struct {
 }
 func (e E_DuplicateBinding) DescribeError() richtext.Block {
 	return makeErrorDescBlock (
-		"duplicate binding",
+		"duplicate binding:",
+		e.BindingName,
+	)
+}
+
+type E_UnusedBinding struct {
+	BindingName  string
+}
+func (e E_UnusedBinding) DescribeError() richtext.Block {
+	return makeErrorDescBlock (
+		"unused binding:",
 		e.BindingName,
 	)
 }
@@ -464,7 +474,7 @@ type E_MissingArgument struct {
 }
 func (e E_MissingArgument) DescribeError() richtext.Block {
 	return makeErrorDescBlock (
-		"missing argument",
+		"missing argument:",
 		e.Name,
 	)
 }
@@ -493,12 +503,12 @@ func (E_UnableToInferVaType) DescribeError() richtext.Block {
 	)
 }
 
-type E_NoSuchReferableGlobalOrBinding struct {
+type E_NoSuchThing struct {
 	Ref  string
 }
-func (e E_NoSuchReferableGlobalOrBinding) DescribeError() richtext.Block {
+func (e E_NoSuchThing) DescribeError() richtext.Block {
 	return makeErrorDescBlock (
-		"no such referable global or binding:",
+		"no such thing:",
 		e.Ref,
 	)
 }
@@ -555,12 +565,12 @@ func (E_SuperfluousTypeArgs) DescribeError() richtext.Block {
 	)
 }
 
-type E_UnableToMakeLambda struct {
+type E_UnableToUseAsLambda struct {
 	InOutDesc  string
 }
-func (e E_UnableToMakeLambda) DescribeError() richtext.Block {
+func (e E_UnableToUseAsLambda) DescribeError() richtext.Block {
 	return makeErrorDescBlock (
-		"unable to make a lambda from a global with signature",
+		"unable to use as lambda: unqualified signature",
 		e.InOutDesc,
 	)
 }
@@ -577,15 +587,22 @@ func (e E_MultipleAssignable) DescribeError() richtext.Block {
 
 type E_NoneAssignable struct {
 	Ref      string
-	Details  [] source.ErrorContent
+	Details  [] NoneAssignableErrorDetail
+}
+type NoneAssignableErrorDetail struct {
+	ItemName      string
+	ErrorContent  source.ErrorContent
 }
 func (e E_NoneAssignable) DescribeError() richtext.Block {
 	var b = makeErrorDescBlock (
-		"unable to find a global available for assignment of",
+		"nothing qualified for assignment of",
 		e.Ref,
 	)
 	for _, detail := range e.Details {
-		b.Append(detail.DescribeError())
+		var desc = detail.ErrorContent.DescribeError()
+		desc = desc.WithoutLeadingSpan()
+		desc = desc.WithLeadingSpan((detail.ItemName + ":"), richtext.TAG_B)
+		b.Append(desc)
 	}
 	return b
 }

+ 79 - 20
interpreter/compiler/expr.go

@@ -29,6 +29,23 @@ func createExprContext(params ([] string), fd fragmentDraft, ctx *NsHeaderMap) *
 		context:  ctx,
 	}
 }
+func (ctx *exprContext) unusedBindingError() *source.Error {
+	if ctx.unused.Size() == 0 {
+		return nil
+	}
+	var bindings = make([] *program.Binding, 0)
+	ctx.unused.ForEach(func(item *program.Binding) {
+		bindings = append(bindings, item)
+	})
+	bindings, _ = ctn.StableSort(bindings, func(a *program.Binding, b *program.Binding) bool {
+		return a.Location.Pos.Span.Start < b.Location.Pos.Span.Start
+	})
+	var first = bindings[0]
+	return source.MakeError(first.Location,
+		E_UnusedBinding {
+			BindingName: first.Name,
+		})
+}
 func (ctx *exprContext) fragmentNamespace() string {
 	return ctx.fragment.namespace()
 }
@@ -36,10 +53,14 @@ func (ctx *exprContext) tryRedirectRef(ref *source.Ref) bool {
 	return ctx.context.tryRedirectRef(ctx.fragmentNamespace(), ref)
 }
 func (ctx *exprContext) createBinding(name string, t typsys.CertainType, loc source.Location) *program.Binding {
+	return ctx.createBinding4(name, t, loc, false)
+}
+func (ctx *exprContext) createBinding4(name string, t typsys.CertainType, loc source.Location, const_ bool) *program.Binding {
 	var binding = &program.Binding {
 		Name:     name,
 		Type:     t,
 		Location: loc,
+		Constant: const_,
 	}
 	ctx.addBinding(binding)
 	return binding
@@ -61,6 +82,15 @@ func (ctx *exprContext) useBinding(name string) (*program.Binding, bool) {
 	}
 	return binding, exists
 }
+func (ctx *exprContext) copyWithNewConstScope() *exprContext {
+	var child = ctx.scope.FilterClone(func(_ string, binding *program.Binding) bool {
+		return binding.Constant
+	})
+	var new_ctx exprContext
+	new_ctx = *ctx
+	new_ctx.scope = child
+	return &new_ctx
+}
 func (ctx *exprContext) copyWithNewBlockScope() *exprContext {
 	var child = ctx.scope.Clone()
 	var new_ctx exprContext
@@ -306,6 +336,9 @@ func (cc *exprCheckContext) try() (*exprCheckContext, **typsys.InferringState) {
 		context:   cc.context,
 	}, S
 }
+func (cc *exprCheckContext) withConstScope() *exprCheckContext {
+	return cc.use(cc.context.copyWithNewConstScope())
+}
 func (cc *exprCheckContext) withBlockScope() *exprCheckContext {
 	return cc.use(cc.context.copyWithNewBlockScope())
 }
@@ -336,9 +369,25 @@ func (cc *exprCheckContext) loadTrialInferringState(S **typsys.InferringState) {
 }
 func (cc *exprCheckContext) checkChildExpr (
 	expected  typsys.Type,
-	expr      ast.Expr,
+	expr_     ast.Expr,
 ) (*program.Expr, *source.Error) {
-	return checkExpr(expr, cc.expect(expected))
+	return cc.checkChildExpr3(expected, expr_, false)
+}
+func (cc *exprCheckContext) checkChildExpr3 (
+	expected  typsys.Type,
+	expr_     ast.Expr,
+	const_    bool,
+) (*program.Expr, *source.Error) {
+	if const_ {
+		// noinspection ALL
+		cc = cc.withConstScope()
+	}
+	var expr, err = checkExpr(expr_, cc.expect(expected))
+	if err != nil { return nil, err }
+	if const_ {
+		expr = program.Cache(expr)
+	}
+	return expr, nil
 }
 func (cc *exprCheckContext) assignChildExpr (
 	expected  typsys.Type,
@@ -459,19 +508,28 @@ func (cc *exprCheckContext) match (
 	pattern  ast.MaybePattern,
 	value_t  typsys.CertainType,
 ) (program.PatternMatching, *source.Error) {
+	return cc.match3(pattern, value_t, false)
+}
+
+func (cc *exprCheckContext) match3 (
+	pattern  ast.MaybePattern,
+	value_t  typsys.CertainType,
+	const_   bool,
+) (program.PatternMatching, *source.Error) {
 	var result = make(program.PatternMatching, 0)
 	if pattern, ok := pattern.(ast.VariousPattern); ok {
 		switch P := pattern.Pattern.(type) {
 		case ast.PatternSingle:
 			var name = ast.Id2String(P.Name)
 			var loc = P.Location
-			if name != Underscore {
-				var b = cc.context.createBinding(name, value_t, loc)
-				result = append(result, program.PatternMatchingItem {
-					Binding: b,
-					Index1:  0,
-				})
+			if name == Underscore {
+				break
 			}
+			var b = cc.context.createBinding4(name, value_t, loc, const_)
+			result = append(result, program.PatternMatchingItem {
+				Binding: b,
+				Index1:  0,
+			})
 		case ast.PatternMultiple:
 			var loc = P.Location
 			var record, def, args, ok = getRecord(value_t.Type, cc.context)
@@ -498,19 +556,20 @@ func (cc *exprCheckContext) match (
 				var field_t = typsys.CertainType { Type: field_t_ }
 				var name = ast.Id2String(binding_node)
 				var loc = binding_node.Location
-				if name != Underscore {
-					var _, duplicate = occurred[name]
-					occurred[name] = struct{}{}
-					if duplicate {
-						return nil, source.MakeError(loc,
-							E_DuplicateBinding { name })
-					}
-					var b = cc.context.createBinding(name, field_t, loc)
-					result = append(result, program.PatternMatchingItem {
-						Binding: b,
-						Index1:  (1 + i),
-					})
+				if name == Underscore {
+					continue
+				}
+				var _, duplicate = occurred[name]
+				occurred[name] = struct{}{}
+				if duplicate {
+					return nil, source.MakeError(loc,
+						E_DuplicateBinding { name })
 				}
+				var b = cc.context.createBinding4(name, field_t, loc, const_)
+				result = append(result, program.PatternMatchingItem {
+					Binding: b,
+					Index1:  (1 + i),
+				})
 			}
 		default:
 			panic("impossible branch")

+ 3 - 7
interpreter/compiler/expr1.go

@@ -94,15 +94,11 @@ func checkBlock(B ast.Block, cc *exprCheckContext) (*program.Expr, *source.Error
 			if B.Off {
 				return cc.forwardTo(rest)
 			}
-			if B.Const {
-				// TODO: const binding (value cannot depend on let bindings)
-				panic("not implemented")
-			}
-			{ var cc = cc.withBlockScope()
-			var val_expr, err = cc.checkChildExpr(nil, B.Value)
+			var val_expr, err = cc.checkChildExpr3(nil, B.Value, B.Const)
 			if err != nil { return nil, err }
 			var val_t = val_expr.Type
-			{ var pm, err = cc.match(B.Pattern, val_t)
+			{ var cc = cc.withBlockScope()
+			{ var pm, err = cc.match3(B.Pattern, val_t, B.Const)
 			if err != nil { return nil, err }
 			{ var rest_expr, err = cc.forwardTo(rest)
 			if err != nil { return nil, err }

+ 20 - 13
interpreter/compiler/expr2.go

@@ -158,12 +158,15 @@ func checkRefTerm(ref_term ast.RefTerm, cc *exprCheckContext) (*program.Expr, *s
 	if err != nil { return nil, err }
 	var options = findFunRefOptions(ref, ctx)
 	if len(options) == 0 {
-		return cc.error(loc,
-			E_NoSuchReferableGlobalOrBinding { ref.String() })
+		return cc.error(loc, E_NoSuchThing { ref.String() })
 	}
-	var trials = ctn.MapEach(options, func(option func()(*funHeader,**program.Function)) func()(*program.Expr,**typsys.InferringState,*source.Error) {
+	var names = ctn.MapEach(options, func(option func()(*funHeader,**program.Function,string)) string {
+		var _, _, name = option()
+		return name
+	})
+	var trials = ctn.MapEach(options, func(option func()(*funHeader,**program.Function,string)) func()(*program.Expr,**typsys.InferringState,*source.Error) {
+		var hdr, f, _ = option()
 		return func() (*program.Expr, **typsys.InferringState, *source.Error) {
-			var hdr, f = option()
 			var Tp = hdr.typeParams
 			var O = hdr.output.type_
 			var E = hdr.inputsExplicit
@@ -192,7 +195,7 @@ func checkRefTerm(ref_term ast.RefTerm, cc *exprCheckContext) (*program.Expr, *s
 				var L, destruct, ok = makeLambdaType(E, O)
 				if !(ok) {
 					return nil, nil, source.MakeError(loc,
-						E_UnableToMakeLambda { describeFunInOut(hdr) })
+						E_UnableToUseAsLambda { describeFunInOut(hdr) })
 				}
 				return cc.tryInfer(Tp, Ta, L, loc, func(cc *exprCheckContext) (program.ExprContent, *source.Error) {
 					return program.FunRef {
@@ -206,8 +209,8 @@ func checkRefTerm(ref_term ast.RefTerm, cc *exprCheckContext) (*program.Expr, *s
 	var ref_expr *program.Expr
 	var ref_S **typsys.InferringState
 	var found = false
-	var errs = make([] source.ErrorContent, 0)
-	for _, trial := range trials {
+	var details = make([] NoneAssignableErrorDetail, 0)
+	for i, trial := range trials {
 		var expr, S, err = trial()
 		if err == nil {
 			if found {
@@ -219,7 +222,10 @@ func checkRefTerm(ref_term ast.RefTerm, cc *exprCheckContext) (*program.Expr, *s
 				found = true
 			}
 		} else {
-			errs = append(errs, err.Content)
+			details = append(details, NoneAssignableErrorDetail {
+				ItemName:     names[i],
+				ErrorContent: err.Content,
+			})
 		}
 	}
 	if found {
@@ -227,7 +233,7 @@ func checkRefTerm(ref_term ast.RefTerm, cc *exprCheckContext) (*program.Expr, *s
 		return ref_expr, nil
 	} else {
 		return cc.error(loc,
-			E_NoneAssignable { ref.String(), errs })
+			E_NoneAssignable { ref.String(), details })
 	}
 }
 
@@ -702,18 +708,19 @@ func mapFieldsType(fields *typsys.Fields, f func(typsys.Type)(typsys.Type)) *typ
 	}
 }
 
-func findFunRefOptions(ref source.Ref, ctx *exprContext) ([] func()(*funHeader,**program.Function)) {
+func findFunRefOptions(ref source.Ref, ctx *exprContext) ([] func()(*funHeader,**program.Function,string)) {
 	var all = ctx.context.lookupReferableFunctions(ref)
 	if len(all) == 0 {
 		if ctx.tryRedirectRef(&ref) {
 			all = ctx.context.lookupReferableFunctions(ref)
 		}
 	}
-	return ctn.MapEach(all, func(item func()(*funHeader,string,userFunKey)) func()(*funHeader,**program.Function) {
+	return ctn.MapEach(all, func(item func()(*funHeader,string,userFunKey)) func()(*funHeader,**program.Function,string) {
 		var hdr, ns, key = item()
 		var f = ctx.fragment.referUserFun(ns, key)
-		var option = func() (*funHeader, **program.Function) {
-			return hdr, f
+		var name = key.Describe(ns)
+		var option = func() (*funHeader, **program.Function, string) {
+			return hdr, f, name
 		}
 		return option
 	})

+ 0 - 0
interpreter/compiler/header.go


Some files were not shown because too many files changed in this diff